diff --git a/.babelrc b/.babelrc deleted file mode 100644 index a9ce1369e..000000000 --- a/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "presets": ["react-native"] -} diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 791c9e806..000000000 --- a/.dockerignore +++ /dev/null @@ -1,21 +0,0 @@ -node_modules -**/node_modules -*node_modules - -# logs -yarn-error.log -npm-debug.log - -# root folders -.github -dockerfiles -.vscode - -# not docker packages -packages/blockchain-api -packages/docs -packages/faucet -packages/mobile -packages/react-components -packages/notification-service -packages/web diff --git a/.env b/.env deleted file mode 100644 index caa932d6c..000000000 --- a/.env +++ /dev/null @@ -1,291 +0,0 @@ -# These are the default values that should apply to most environments, especially dev ones -ENV_TYPE="development" - -GETH_DEBUG=true -GETH_VERBOSITY=1 -# Per-module verbosity: comma-separated list of = (e.g. eth/*=5,p2p=4, consensus/*=4) -GETH_VMODULE="consensus/*=2" -GETH_ENABLE_METRICS=false -GETH_USE_MYCELO=false - -KUBERNETES_CLUSTER_NAME="celo-networks-dev" -KUBERNETES_CLUSTER_ZONE="us-west1-a" -CLUSTER_DOMAIN_NAME="celo-networks-dev" - -TESTNET_PROJECT_NAME="celo-testnet" - -BLOCKSCOUT_DOCKER_IMAGE_TAG="5f546f4e479fc51817fa324149002ce70478389a" -BLOCKSCOUT_DB_SUFFIX= - -# Blockscout related cronjobs -LEADERBOARD_DOCKER_IMAGE_REPOSITORY="us.gcr.io/celo-testnet/celo-monorepo" -LEADERBOARD_DOCKER_IMAGE_TAG="leaderboard-2708d6459b6efe2ab3ec04084d9c3819e202699f" - -CELOSTATS_SERVER_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/celostats-server" -CELOSTATS_SERVER_DOCKER_IMAGE_TAG="28b3e8a3a03f3926524ccc5b9cff04d256b5a3a9" -CELOSTATS_FRONTEND_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/celostats-frontend" -CELOSTATS_FRONTEND_DOCKER_IMAGE_TAG="d092a2d527f64cabbb4364b72eb72faf364c6156" -CELOSTATS_TRUSTED_ADDRESSES="" -CELOSTATS_BANNED_ADDRESSES="" -CELOSTATS_RESERVED_ADDRESSES="" - -FAUCET_GENESIS_ACCOUNTS=2 - -GETH_NODE_DOCKER_IMAGE_REPOSITORY="us.gcr.io/celo-testnet/geth" -# When upgrading change this to latest commit hash from the master of the geth repo -# `geth $ git show | head -n 1` -GETH_NODE_DOCKER_IMAGE_TAG="master" - -GETH_BOOTNODE_DOCKER_IMAGE_REPOSITORY="us.gcr.io/celo-testnet/geth-all" -# When upgrading change this to latest commit hash from the master of the geth repo -# `geth $ git show | head -n 1` -GETH_BOOTNODE_DOCKER_IMAGE_TAG="master" - -CELOTOOL_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/celo-monorepo" -CELOTOOL_DOCKER_IMAGE_TAG="celotool-4257fe61f91e935681f3a91bb4dcb44c8dd6df47" - -CELOCLI_STANDALONE_IMAGE_REPOSITORY="gcr.io/celo-testnet/celocli-standalone" -CELOCLI_STANDALONE_IMAGE_TAG="0.0.30-beta2" - -# Schedule for an oracle deployed via celotool, expressed in crontab syntax -# This schedule is "every 5th minute" -MOCK_ORACLE_CRON_SCHEDULE="*/5 * * * *" - -MOCK_ORACLE_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/oracle" -MOCK_ORACLE_DOCKER_IMAGE_TAG="default" - -TRANSACTION_METRICS_EXPORTER_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/celo-monorepo" -TRANSACTION_METRICS_EXPORTER_DOCKER_IMAGE_TAG="transaction-metrics-exporter-dc5e5dfa07231a4ff4664816a95eae606293eae9" -TRANSACTION_METRICS_EXPORTER_SUFFIX='1' - -# Genesis Vars -NETWORK_ID=1101 -CONSENSUS_TYPE="istanbul" -BLOCK_TIME=1 -EPOCH=1000 -LOOKBACK=12 -ISTANBUL_REQUEST_TIMEOUT_MS=3000 -# Hardfork activation block numbers (also part of genesis) -CHURRITO_BLOCK=0 -DONUT_BLOCK=0 - -# the number of load test clients that will be given funds in the genesis & migrations -LOAD_TEST_CLIENTS=100 -# every 36 seconds, so that 100 transactions are sent by a client every hour -LOAD_TEST_TX_DELAY_MS=36000 - -LOAD_TEST_USE_RANDOM_RECIPIENT='false' - -# the amount in cUSD wei to give faucet, load test, and attestation bot accounts -FAUCET_CUSD_WEI=60000000000000000000000 - -VALIDATORS="3" - -# format: <# of validators>:,<# of validators>:;... -# For vm-based testnets: The n proxied validators have to be the n first validators. Only indicate in the list the validators with proxy. -# Example: For a 10 validator testnet, 2:3,2:2,2:1 will result in Validator 0-1 with 3 proxies, 2-3 with 2 proxies, 4-5 with 1 proxy, and 6-9 with 0 proxies -VALIDATOR_PROXY_COUNTS=1:1,2:0 -STATIC_IPS_FOR_GETH_NODES=false -# Whether tx_nodes/validators stateful set should use ssd persistent disks -GETH_NODES_SSD_DISKS=true -# Used for validators, proxies, and tx_nodes -NODE_DISK_SIZE_GB=10 -# Used for private tx_nodes (gcmode archive) -PRIVATE_NODE_DISK_SIZE_GB=10 -IN_MEMORY_DISCOVERY_TABLE=false - -TX_NODES="3" -# Nodes whose RPC ports are only internally exposed -PRIVATE_TX_NODES=1 - -# Canary Deployment Variables -# Specify the partition nodes to be using a new statefulset definition. The number of the nodes -# specified in the partition are the nodes using the old definition. Use 0 for all the replicas -# using the latest definition -# https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#partitions -VALIDATORS_ROLLING_UPDATE_PARTITION=0 -PROXY_ROLLING_UPDATE_PARTITION=0 -SECONDARIES_ROLLING_UPDATE_PARTITION=0 -TX_NODES_ROLLING_UPDATE_PARTITION=0 -TX_NODES_PRIVATE_ROLLING_UPDATE_PARTITION=0 - -# Kubernetes Cluster Creation flags. Only used when a new kubernetes cluster needs to be created -CLUSTER_CREATION_FLAGS="--enable-autoscaling --min-nodes 3 --max-nodes 40 --machine-type=n1-standard-4 --preemptible --workload-metadata=GKE_METADATA --workload-pool=celo-testnet.svc.id.goog" - -# Number of faulty/Byzantine validators -FAULTY_VALIDATORS=0 - -# What type of Byzantine fault the faulty validators exhibit: -# see valid values at geth/consensus/istanbul/config.go line 28 -FAULTY_VALIDATOR_TYPE=1 - -GETH_NODE_CPU_REQUEST=400m -GETH_NODE_MEMORY_REQUEST=800M - -VERIFICATION_POOL_URL="https://us-central1-celo-testnet.cloudfunctions.net/handleVerificationRequestintegration/v0.1/sms/" -VERIFICATION_REWARDS_URL="https://us-central1-celo-testnet.cloudfunctions.net/handleVerificationRequestintegration/v0.1/rewards/" - -# Disable the sidecar that forwards the metrics to stackdriver -PROMETHEUS_DISABLE_STACKDRIVER_SIDECAR="true" - -# To not deploy the start-auction cronjob, set this value to the empty string -AUCTION_CRON_SPEC= - -# Chaos testing variables -CHAOS_TEST_INTERVAL = 3m -CHAOS_TEST_DURATION = 2m -# in milliseconds -CHAOS_TEST_NETWORK_DELAY = 1400 -CHAOS_TEST_NETWORK_JITTER = 500 -CHAOS_TEST_NETWORK_LOSS = 80 -CHAOS_TEST_NETWORK_RATE = 100kbit -CHAOS_TEST_KILL_INTERVAL = 3m - -# Below are variables for which there exist no sensible defaults, and thus should -# be customized in their respective .env.$CELO_ENV files -# -# MOBILE_WALLET_PLAYSTORE_LINK="" - -# Number of gold-holding bots that vote for validator groups -VOTING_BOTS=3 -# 10,000 CG -VOTING_BOT_BALANCE=10000000000000000000000 -# Probability that a given bot account will participate in the current epoch's voting -VOTING_BOT_WAKE_PROBABILITY=0.2 -# Baseline probability of changing vote once woken. If the group that this bot account -# has currently voted for is 1, this is the probability the bot will change their vote -VOTING_BOT_CHANGE_BASELINE=0.1 - -# The probability that when choosing a new group to vote for, it will choose a never-elected group -# Should be in the range of 0 to 1. Lower values bias towards incumbency. Higher values bias -# towards novelty. -VOTING_BOT_EXPLORE_PROBABILITY=0.7 - -# This value is used to determine how heavily a group's score weigh in the bot's voting decision -# Should be a positive number. 1 is a linear relationship. Higher values increase the separation -# among high scores. -VOTING_BOT_SCORE_SENSITIVITY=5 - -# Schedule for the voting bot process, deployed via celotool, expressed in crontab syntax -# This should run roughly once an epoch, but since epoch length is 16.66667 minutes, this -# is not easily represented. -# This schedule is "every 15 minutes", which is close enough. For some epochs, it will run twice -VOTING_BOT_CRON_SCHEDULE="*/15 * * * *" - -# For ODIS e2e tests -ODIS_SIGNER_SERVICE_URL=https://staging-pgpnp-signer0.azurefd.net -ODIS_COMBINER_SERVICE_URL=https://us-central1-celo-phone-number-privacy-stg.cloudfunctions.net -ODIS_BLOCKCHAIN_PROVIDER=https://alfajores-forno.celo-testnet.org - -# For WalletConnect relay -WALLET_CONNECT_IMAGE_REPOSITORY = 'us.gcr.io/celo-testnet/walletconnect' -WALLET_CONNECT_IMAGE_TAG = '1472bcaad57e3746498f7a661c42ff5cf9acaf5a' -WALLET_CONNECT_REDIS_CLUSTER_ENABLED = false -WALLET_CONNECT_REDIS_CLUSTER_USEPASSWORD = false - - -# For dynamic environment variables -# each context should have its own environment variables, generally of the form -# _* -CONTEXTS=azure-odis0-centralus,azure-odis1-centralus,azure-odis2-centralus - -# ODIS azure k8s deployments -ODIS_SIGNER_DOCKER_IMAGE_REPOSITORY=us.gcr.io/celo-testnet/celo-monorepo -ODIS_SIGNER_DOCKER_IMAGE_TAG=oblivious-decentralized-identifier-service-1.1.10 -ODIS_SIGNER_BLOCKCHAIN_PROVIDER=https://alfajores-forno.celo-testnet.org -ODIS_SIGNER_DOMAINS_API_ENABLED=true -ODIS_SIGNER_PNP_API_ENABLED=true -ODIS_SIGNER_LEGACY_PNP_API_ENABLED=true - -# ODIS signer 0 Azure info -AZURE_ODIS0_CENTRALUS_AZURE_SUBSCRIPTION_ID=97e2b592-255b-4f92-bce0-127257163c36 -AZURE_ODIS0_CENTRALUS_AZURE_TENANT_ID=7cb7628a-e37c-4afb-8332-2029e418980e -AZURE_ODIS0_CENTRALUS_AZURE_REGION_NAME=cus - -# ODIS signer 0 K8S cluster info -AZURE_ODIS0_CENTRALUS_AZURE_KUBERNETES_RESOURCE_GROUP=staging-pgpnp-centralus -AZURE_ODIS0_CENTRALUS_KUBERNETES_CLUSTER_NAME=staging-odis0-centralus - -# ODIS signer 0 Postgres DB -AZURE_ODIS0_CENTRALUS_ODIS_SIGNER_DB_HOST=staging-pgpnp-centralus.postgres.database.azure.com -AZURE_ODIS0_CENTRALUS_ODIS_SIGNER_DB_PORT=5432 -AZURE_ODIS0_CENTRALUS_ODIS_SIGNER_DB_USERNAME=pgpnp@staging-pgpnp-centralus - -# ODIS signer 0 Key Vault -AZURE_ODIS0_CENTRALUS_ODIS_SIGNER_AZURE_KEYVAULT_NAME=staging-pgpnp-cus -AZURE_ODIS0_CENTRALUS_ODIS_SIGNER_AZURE_KEYVAULT_PNP_KEY_NAME_BASE=phoneNumberPrivacy0 -AZURE_ODIS0_CENTRALUS_ODIS_SIGNER_AZURE_KEYVAULT_PNP_KEY_LATEST_VERSION=1 -AZURE_ODIS0_CENTRALUS_ODIS_SIGNER_AZURE_KEYVAULT_DOMAINS_KEY_NAME_BASE=domains0 -AZURE_ODIS0_CENTRALUS_ODIS_SIGNER_AZURE_KEYVAULT_DOMAINS_KEY_LATEST_VERSION=1 - -# ODIS signer 0 Network -AZURE_ODIS0_CENTRALUS_ODIS_NETWORK=staging - -# ODIS signer 0 Prometheus config -AZURE_ODIS0_CENTRALUS_PROM_SCRAPE_JOB_NAME=scrape-odis -AZURE_ODIS0_CENTRALUS_PROM_SCRAPE_LABELS="_generic_location: us-central1,_generic_namespace: odis-signer" -AZURE_ODIS0_CENTRALUS_PROM_SCRAPE_TARGETS="staging-odis-signer.staging:3000" -AZURE_ODIS0_CENTRALUS_PROM_SIDECAR_GCP_PROJECT=celo-phone-number-privacy-stg -AZURE_ODIS0_CENTRALUS_PROM_SIDECAR_GCP_REGION=us-east1 -AZURE_ODIS0_CENTRALUS_PROM_SIDECAR_DISABLED="true" - - - -# ODIS signer 1 Azure info -AZURE_ODIS1_CENTRALUS_AZURE_SUBSCRIPTION_ID=97e2b592-255b-4f92-bce0-127257163c36 -AZURE_ODIS1_CENTRALUS_AZURE_TENANT_ID=7cb7628a-e37c-4afb-8332-2029e418980e -AZURE_ODIS1_CENTRALUS_AZURE_REGION_NAME=cus - -# ODIS signer 1 K8S cluster info -AZURE_ODIS1_CENTRALUS_AZURE_KUBERNETES_RESOURCE_GROUP=staging-pgpnp-centralus -AZURE_ODIS1_CENTRALUS_KUBERNETES_CLUSTER_NAME=staging-odis1-centralus - -# ODIS signer 1 Postgres DB -AZURE_ODIS1_CENTRALUS_ODIS_SIGNER_DB_HOST=staging-pgpnp1-centralus.postgres.database.azure.com -AZURE_ODIS1_CENTRALUS_ODIS_SIGNER_DB_PORT=5432 -AZURE_ODIS1_CENTRALUS_ODIS_SIGNER_DB_USERNAME=pgpnp@staging-pgpnp1-centralus - -# ODIS Signer 1 Key Vault -AZURE_ODIS1_CENTRALUS_ODIS_SIGNER_AZURE_KEYVAULT_NAME=staging-pgpnp-cus -AZURE_ODIS1_CENTRALUS_ODIS_SIGNER_AZURE_KEYVAULT_PNP_KEY_NAME_BASE=phoneNumberPrivacy1 -AZURE_ODIS1_CENTRALUS_ODIS_SIGNER_AZURE_KEYVAULT_PNP_KEY_LATEST_VERSION=1 -AZURE_ODIS1_CENTRALUS_ODIS_SIGNER_AZURE_KEYVAULT_DOMAINS_KEY_NAME_BASE=domains1 -AZURE_ODIS1_CENTRALUS_ODIS_SIGNER_AZURE_KEYVAULT_DOMAINS_KEY_LATEST_VERSION=1 - -# ODIS Signer 1 Prometheus config -AZURE_ODIS1_CENTRALUS_PROM_SCRAPE_JOB_NAME=scrape-odis -AZURE_ODIS1_CENTRALUS_PROM_SCRAPE_LABELS="_generic_location: us-central1,_generic_namespace: odis-signer" -AZURE_ODIS1_CENTRALUS_PROM_SCRAPE_TARGETS="staging-odis-signer.staging:3000" -AZURE_ODIS1_CENTRALUS_PROM_SIDECAR_GCP_PROJECT=celo-phone-number-privacy-stg -AZURE_ODIS1_CENTRALUS_PROM_SIDECAR_GCP_REGION=us-east1 -AZURE_ODIS1_CENTRALUS_PROM_SIDECAR_DISABLED="true" - - -# ODIS signer 2 Azure info -AZURE_ODIS2_CENTRALUS_AZURE_SUBSCRIPTION_ID=97e2b592-255b-4f92-bce0-127257163c36 -AZURE_ODIS2_CENTRALUS_AZURE_TENANT_ID=7cb7628a-e37c-4afb-8332-2029e418980e -AZURE_ODIS2_CENTRALUS_AZURE_REGION_NAME=cus - -# ODIS signer 2 K8S cluster info -AZURE_ODIS2_CENTRALUS_AZURE_KUBERNETES_RESOURCE_GROUP=staging-pgpnp-centralus -AZURE_ODIS2_CENTRALUS_KUBERNETES_CLUSTER_NAME=staging-odis2-centralus - -# ODIS signer 2 Postgres DB -AZURE_ODIS2_CENTRALUS_ODIS_SIGNER_DB_HOST=staging-pgpnp2-centralus.postgres.database.azure.com -AZURE_ODIS2_CENTRALUS_ODIS_SIGNER_DB_PORT=5432 -AZURE_ODIS2_CENTRALUS_ODIS_SIGNER_DB_USERNAME=pgpnp@staging-pgpnp2-centralus - -# ODIS Signer 2 Key Vault -AZURE_ODIS2_CENTRALUS_ODIS_SIGNER_AZURE_KEYVAULT_NAME=staging-pgpnp-cus -AZURE_ODIS2_CENTRALUS_ODIS_SIGNER_AZURE_KEYVAULT_PNP_KEY_NAME_BASE=phoneNumberPrivacy2 -AZURE_ODIS2_CENTRALUS_ODIS_SIGNER_AZURE_KEYVAULT_PNP_KEY_LATEST_VERSION=1 -AZURE_ODIS2_CENTRALUS_ODIS_SIGNER_AZURE_KEYVAULT_DOMAINS_KEY_NAME_BASE=domains2 -AZURE_ODIS2_CENTRALUS_ODIS_SIGNER_AZURE_KEYVAULT_DOMAINS_KEY_LATEST_VERSION=1 - -# ODIS Signer 2 Prometheus config -AZURE_ODIS2_CENTRALUS_PROM_SCRAPE_JOB_NAME=scrape-odis -AZURE_ODIS2_CENTRALUS_PROM_SCRAPE_LABELS="_generic_location: us-central1,_generic_namespace: odis-signer" -AZURE_ODIS2_CENTRALUS_PROM_SCRAPE_TARGETS="staging-odis-signer.staging:3000" -AZURE_ODIS2_CENTRALUS_PROM_SIDECAR_GCP_PROJECT=celo-phone-number-privacy-stg -AZURE_ODIS2_CENTRALUS_PROM_SIDECAR_GCP_REGION=us-east1 -AZURE_ODIS2_CENTRALUS_PROM_SIDECAR_DISABLED="true" diff --git a/.env.alfajores b/.env.alfajores deleted file mode 100644 index f0e56cc1f..000000000 --- a/.env.alfajores +++ /dev/null @@ -1,242 +0,0 @@ -ENV_TYPE="production" - -GETH_VERBOSITY=2 - -KUBERNETES_CLUSTER_NAME="alfajores" -KUBERNETES_CLUSTER_ZONE="us-west1-a" -CLUSTER_DOMAIN_NAME="celo-testnet" - -TESTNET_PROJECT_NAME="celo-testnet-production" - -BLOCKSCOUT_DOCKER_IMAGE_TAG="0362f9f4d1d4842f27adb634d628f969f53c046d" -# Assign a new value everytime you redeploy blockscout. Or else the deployment will fail due to the -# existing database. -BLOCKSCOUT_DB_SUFFIX="2" -FAUCET_GENESIS_ACCOUNTS=2 - -CELOSTATS_SERVER_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/celostats-server" -CELOSTATS_SERVER_DOCKER_IMAGE_TAG="master" -CELOSTATS_FRONTEND_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/celostats-frontend" -CELOSTATS_FRONTEND_DOCKER_IMAGE_TAG="master" -CELOSTATS_TRUSTED_ADDRESSES="" -CELOSTATS_BANNED_ADDRESSES="" -CELOSTATS_RESERVED_ADDRESSES="" - -ORACLE_DOCKER_IMAGE_REPOSITORY="us-west1-docker.pkg.dev/celo-testnet-production/celo-oracle/celo-oracle" -ORACLE_DOCKER_IMAGE_TAG="1.0.7" - -AZURE_ORACLE_CENTRALUS_AZURE_SUBSCRIPTION_ID=7a6f5f20-bd43-4267-8c35-a734efca140c -AZURE_ORACLE_CENTRALUS_AZURE_TENANT_ID=7cb7628a-e37c-4afb-8332-2029e418980e -AZURE_ORACLE_CENTRALUS_AZURE_KUBERNETES_RESOURCE_GROUP=baklava-oracles-centralus -AZURE_ORACLE_CENTRALUS_KUBERNETES_CLUSTER_NAME=baklava-oracles-centralus -AZURE_ORACLE_CENTRALUS_AZURE_REGION_NAME=centralus -AZURE_ORACLE_CENTRALUS_CELOUSD_ORACLE_ADDRESSES_FROM_MNEMONIC_COUNT=4 -AZURE_ORACLE_CENTRALUS_CELOEUR_ORACLE_ADDRESSES_FROM_MNEMONIC_COUNT=4 -AZURE_ORACLE_CENTRALUS_CELOBRL_ORACLE_ADDRESSES_FROM_MNEMONIC_COUNT=4 -AZURE_ORACLE_CENTRALUS_USDCUSD_ORACLE_ADDRESSES_FROM_MNEMONIC_COUNT=4 -AZURE_ORACLE_CENTRALUS_USDCEUR_ORACLE_ADDRESSES_FROM_MNEMONIC_COUNT=4 -AZURE_ORACLE_CENTRALUS_USDCBRL_ORACLE_ADDRESSES_FROM_MNEMONIC_COUNT=4 -AZURE_ORACLE_CENTRALUS_EUROCEUR_ORACLE_ADDRESSES_FROM_MNEMONIC_COUNT=4 -AZURE_ORACLE_CENTRALUS_CELOXOF_ORACLE_ADDRESSES_FROM_MNEMONIC_COUNT=4 -AZURE_ORACLE_CENTRALUS_EURXOF_ORACLE_ADDRESSES_FROM_MNEMONIC_COUNT=4 -AZURE_ORACLE_CENTRALUS_EUROCXOF_ORACLE_ADDRESSES_FROM_MNEMONIC_COUNT=4 -AZURE_ORACLE_CENTRALUS_FULL_NODES_COUNT=2 -AZURE_ORACLE_CENTRALUS_FULL_NODES_DISK_SIZE=30 -AZURE_ORACLE_CENTRALUS_FULL_NODES_ROLLING_UPDATE_PARTITION=0 -AZURE_ORACLE_CENTRALUS_FULL_NODES_RPC_API_METHODS="eth,net,rpc,web3" -AZURE_ORACLE_CENTRALUS_FULL_NODES_GETH_GC_MODE="full" -AZURE_ORACLE_CENTRALUS_FULL_NODES_USE_GSTORAGE_DATA=false -AZURE_ORACLE_CENTRALUS_FULL_NODES_WS_PORT="8546" - -# Temporarily point to celo-org repository to consume patched image. -GETH_NODE_DOCKER_IMAGE_REPOSITORY="us.gcr.io/celo-org/geth" -GETH_NODE_DOCKER_IMAGE_TAG="1.7.2" - -GETH_BOOTNODE_DOCKER_IMAGE_REPOSITORY="us.gcr.io/celo-org/geth-all" -GETH_BOOTNODE_DOCKER_IMAGE_TAG="1.7.2" - -# Enable pprof and prometheus scrape labels -GETH_ENABLE_METRICS=true - -# Disable the sidecar that forwards the metrics to stackdriver -PROMETHEUS_DISABLE_STACKDRIVER_SIDECAR="true" - -CELOTOOL_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/celo-monorepo" -CELOTOOL_DOCKER_IMAGE_TAG="celotool-4257fe61f91e935681f3a91bb4dcb44c8dd6df47" - -CELOCLI_STANDALONE_IMAGE_REPOSITORY="gcr.io/celo-testnet/celocli-standalone" -CELOCLI_STANDALONE_IMAGE_TAG="0.0.53" - -# Schedule for an oracle deployed via celotool, expressed in crontab syntax -# This schedule is "every 5th minute" -MOCK_ORACLE_CRON_SCHEDULE="*/5 * * * *" - -MOCK_ORACLE_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/oracle" -MOCK_ORACLE_DOCKER_IMAGE_TAG="default" - -TRANSACTION_METRICS_EXPORTER_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/celo-monorepo" -TRANSACTION_METRICS_EXPORTER_DOCKER_IMAGE_TAG="transaction-metrics-exporter-f4a55e143932ea559cf4bcbd9bcccc14da43d6ed" - -# Genesis Vars -NETWORK_ID=44787 -CONSENSUS_TYPE="istanbul" -BLOCK_TIME=5 -# Epoch length is 1 day -EPOCH=17280 -LOOKBACK=12 -ISTANBUL_REQUEST_TIMEOUT_MS=10000 - -# the number of load test clients that will be given funds in the genesis & migrations -LOAD_TEST_CLIENTS=20 -# every 7.2 seconds, so that 500 transactions are sent by a client every hour -# to simulate 10,000 total transactions per hour -LOAD_TEST_TX_DELAY_MS=7200 - -# the amount in cUSD wei to give faucet, load test, and attestation bot accounts -FAUCET_CUSD_WEI=60000000000000000000000 - -VALIDATORS=10 -VALIDATOR_PROXY_COUNTS=10:0 - -TX_NODES=4 -# Nodes whose RPC ports are only internally exposed -PRIVATE_TX_NODES=2 -STATIC_IPS_FOR_GETH_NODES=true -# Whether tx_nodes/validators stateful set should use ssd persistent disks -GETH_NODES_SSD_DISKS=true -# Used for validators, proxies, and tx_nodes -NODE_DISK_SIZE_GB=30 -# Used for private tx_nodes (gcmode archive) -PRIVATE_NODE_DISK_SIZE_GB=80 -IN_MEMORY_DISCOVERY_TABLE=true -PING_IP_FROM_PACKET=true - -# Testnet vars -CLUSTER_CREATION_FLAGS="--enable-autoscaling --min-nodes 3 --max-nodes 8 --machine-type=n1-standard-4" - -GETH_NODE_CPU_REQUEST=2 -GETH_NODE_MEMORY_REQUEST=4Gi - -VERIFICATION_POOL_URL="https://us-central1-celo-testnet-production.cloudfunctions.net/handleVerificationRequestalfajores/v0.1/sms/" -VERIFICATION_REWARDS_URL="https://us-central1-celo-testnet-production.cloudfunctions.net/handleVerificationRequestalfajores/v0.1/rewards/" - -MOBILE_WALLET_PLAYSTORE_LINK="https://play.google.com/apps/internaltest/4700990475000634666" - -# each context should have its own environment variables, generally of the form -# _* -CONTEXTS=azure-oracle-centralus,azure-odis-eastus-1,azure-odis-eastus-2,azure-odis-eastus-3 - -# --- ODIS --- - -# ODIS azure k8s deployments -ODIS_SIGNER_DOCKER_IMAGE_REPOSITORY=us.gcr.io/celo-testnet/celo-monorepo -ODIS_SIGNER_DOCKER_IMAGE_TAG=oblivious-decentralized-identifier-service-1.1.10 -ODIS_SIGNER_BLOCKCHAIN_PROVIDER=https://alfajores-forno.celo-testnet.org -# Options: json, human (default), stackdriver -LOG_FORMAT=stackdriver -# Options: fatal, error, warn, info (default), debug, trace -LOG_LEVEL=info - -# ODIS signer 1 Azure info -AZURE_ODIS_EASTUS_1_AZURE_SUBSCRIPTION_ID=97e2b592-255b-4f92-bce0-127257163c36 -AZURE_ODIS_EASTUS_1_AZURE_TENANT_ID=7cb7628a-e37c-4afb-8332-2029e418980e -AZURE_ODIS_EASTUS_1_AZURE_REGION_NAME=eaus - -# ODIS signer 1 K8S cluster info -AZURE_ODIS_EASTUS_1_AZURE_KUBERNETES_RESOURCE_GROUP=pgpnp-alfajores -AZURE_ODIS_EASTUS_1_KUBERNETES_CLUSTER_NAME=odis-alfajores-signer-1-a-v2 - -# ODIS signer 1 Postgres DB -AZURE_ODIS_EASTUS_1_ODIS_SIGNER_DB_HOST=pgpnp-alfajores-db1v2.postgres.database.azure.com -AZURE_ODIS_EASTUS_1_ODIS_SIGNER_DB_PORT=5432 -AZURE_ODIS_EASTUS_1_ODIS_SIGNER_DB_USERNAME=cLabs@pgpnp-alfajores-db1v2 - -# ODIS signer 1 Key Vault -AZURE_ODIS_EASTUS_1_ODIS_SIGNER_AZURE_KEYVAULT_NAME=pgpnp-alfajores-kv1 -AZURE_ODIS_EASTUS_1_ODIS_SIGNER_AZURE_KEYVAULT_PNP_KEY_NAME_BASE=phoneNumberPrivacy -AZURE_ODIS_EASTUS_1_ODIS_SIGNER_AZURE_KEYVAULT_PNP_KEY_LATEST_VERSION=1 -AZURE_ODIS_EASTUS_1_ODIS_SIGNER_AZURE_KEYVAULT_DOMAINS_KEY_NAME_BASE=domains -AZURE_ODIS_EASTUS_1_ODIS_SIGNER_AZURE_KEYVAULT_DOMAINS_KEY_LATEST_VERSION=1 - -# ODIS signer 1 Network -AZURE_ODIS_EASTUS_1_ODIS_NETWORK=alfajores - -# ODIS signer 1 Prometheus config -AZURE_ODIS_EASTUS_1_PROM_SCRAPE_JOB_NAME=scrape-odis -AZURE_ODIS_EASTUS_1_PROM_SCRAPE_LABELS="_generic_location: us-central1,_generic_namespace: odis-signer" -AZURE_ODIS_EASTUS_1_PROM_SCRAPE_TARGETS="odis-alfajores-signer-1-a-v2.alfajores:3000" -AZURE_ODIS_EASTUS_1_PROM_SIDECAR_GCP_PROJECT=celo-phone-number-privacy -AZURE_ODIS_EASTUS_1_PROM_SIDECAR_GCP_REGION=us-east1 -AZURE_ODIS_EASTUS_1_PROM_SIDECAR_DISABLED="true" - - -# ODIS signer 2 Azure info -AZURE_ODIS_EASTUS_2_AZURE_SUBSCRIPTION_ID=97e2b592-255b-4f92-bce0-127257163c36 -AZURE_ODIS_EASTUS_2_AZURE_TENANT_ID=7cb7628a-e37c-4afb-8332-2029e418980e -AZURE_ODIS_EASTUS_2_AZURE_REGION_NAME=eaus - -# ODIS signer 2 K8S cluster info -AZURE_ODIS_EASTUS_2_AZURE_KUBERNETES_RESOURCE_GROUP=pgpnp-alfajores -AZURE_ODIS_EASTUS_2_KUBERNETES_CLUSTER_NAME=odis-alfajores-signer-2-b-v2 - -# ODIS signer 2 Postgres DB -AZURE_ODIS_EASTUS_2_ODIS_SIGNER_DB_HOST=pgpnp-alfajores-db2v2.postgres.database.azure.com -AZURE_ODIS_EASTUS_2_ODIS_SIGNER_DB_PORT=5432 -AZURE_ODIS_EASTUS_2_ODIS_SIGNER_DB_USERNAME=clabs@pgpnp-alfajores-db2v2 - -# ODIS signer 2 Key Vault -AZURE_ODIS_EASTUS_2_ODIS_SIGNER_AZURE_KEYVAULT_NAME=pgpnp-alfajores-kv2 -AZURE_ODIS_EASTUS_2_ODIS_SIGNER_AZURE_KEYVAULT_PNP_KEY_NAME_BASE=phoneNumberPrivacy -AZURE_ODIS_EASTUS_2_ODIS_SIGNER_AZURE_KEYVAULT_PNP_KEY_LATEST_VERSION=1 -AZURE_ODIS_EASTUS_2_ODIS_SIGNER_AZURE_KEYVAULT_DOMAINS_KEY_NAME_BASE=domains -AZURE_ODIS_EASTUS_2_ODIS_SIGNER_AZURE_KEYVAULT_DOMAINS_KEY_LATEST_VERSION=1 - -# ODIS signer 2 Network -AZURE_ODIS_EASTUS_2_ODIS_NETWORK=alfajores - -# ODIS signer 2 Prometheus config -AZURE_ODIS_EASTUS_2_PROM_SCRAPE_JOB_NAME=scrape-odis -AZURE_ODIS_EASTUS_2_PROM_SCRAPE_LABELS="_generic_location: us-central1,_generic_namespace: odis-signer" -AZURE_ODIS_EASTUS_2_PROM_SCRAPE_TARGETS="odis-alfajores-signer-2-b-v2.alfajores:3000" -AZURE_ODIS_EASTUS_2_PROM_SIDECAR_GCP_PROJECT=celo-phone-number-privacy -AZURE_ODIS_EASTUS_2_PROM_SIDECAR_GCP_REGION=us-east1 -AZURE_ODIS_EASTUS_2_PROM_SIDECAR_DISABLED="true" - - -# ODIS signer 3 Azure info -AZURE_ODIS_EASTUS_3_AZURE_SUBSCRIPTION_ID=97e2b592-255b-4f92-bce0-127257163c36 -AZURE_ODIS_EASTUS_3_AZURE_TENANT_ID=7cb7628a-e37c-4afb-8332-2029e418980e -AZURE_ODIS_EASTUS_3_AZURE_REGION_NAME=eaus - -# ODIS signer 3 K8S cluster info -AZURE_ODIS_EASTUS_3_AZURE_KUBERNETES_RESOURCE_GROUP=pgpnp-alfajores -AZURE_ODIS_EASTUS_3_KUBERNETES_CLUSTER_NAME=odis-alfajores-signer-3-a-v2 - -# ODIS signer 3 Postgres DB -AZURE_ODIS_EASTUS_3_ODIS_SIGNER_DB_HOST=pgpnp-alfajores-db3v2.postgres.database.azure.com -AZURE_ODIS_EASTUS_3_ODIS_SIGNER_DB_PORT=5432 -AZURE_ODIS_EASTUS_3_ODIS_SIGNER_DB_USERNAME=cLabs@pgpnp-alfajores-db3v2 - -# ODIS signer 3 Key Vault -AZURE_ODIS_EASTUS_3_ODIS_SIGNER_AZURE_KEYVAULT_NAME=pgpnp-alfajores-kv3 -AZURE_ODIS_EASTUS_3_ODIS_SIGNER_AZURE_KEYVAULT_PNP_KEY_NAME_BASE=phoneNumberPrivacy -AZURE_ODIS_EASTUS_3_ODIS_SIGNER_AZURE_KEYVAULT_PNP_KEY_LATEST_VERSION=1 -AZURE_ODIS_EASTUS_3_ODIS_SIGNER_AZURE_KEYVAULT_DOMAINS_SECRET_NAME=domains -AZURE_ODIS_EASTUS_3_ODIS_SIGNER_AZURE_KEYVAULT_DOMAINS_KEY_LATEST_VERSION=1 - -# ODIS signer 3 Network -AZURE_ODIS_EASTUS_3_ODIS_NETWORK=alfajores - -# ODIS signer 3 Prometheus config -AZURE_ODIS_EASTUS_3_PROM_SCRAPE_JOB_NAME=scrape-odis -AZURE_ODIS_EASTUS_3_PROM_SCRAPE_LABELS="_generic_location: us-central1,_generic_namespace: odis-signer" -AZURE_ODIS_EASTUS_3_PROM_SCRAPE_TARGETS="odis-alfajores-signer-3-a-v2.alfajores:3000" -AZURE_ODIS_EASTUS_3_PROM_SIDECAR_GCP_PROJECT=celo-phone-number-privacy -AZURE_ODIS_EASTUS_3_PROM_SIDECAR_GCP_REGION=us-east1 -AZURE_ODIS_EASTUS_3_PROM_SIDECAR_DISABLED="true" - -# For WalletConnect relay -WALLET_CONNECT_IMAGE_REPOSITORY = 'us.gcr.io/celo-testnet/walletconnect' -WALLET_CONNECT_IMAGE_TAG = '1472bcaad57e3746498f7a661c42ff5cf9acaf5a' -WALLET_CONNECT_REDIS_CLUSTER_ENABLED = false -WALLET_CONNECT_REDIS_CLUSTER_USEPASSWORD = false diff --git a/.env.baklava b/.env.baklava deleted file mode 100644 index ca394ac05..000000000 --- a/.env.baklava +++ /dev/null @@ -1,228 +0,0 @@ -# Don't use "//" for comments in this file. -# This file is meant to be executed as a bash script for testing. -ENV_TYPE="production" - -GETH_VERBOSITY=2 -GETH_ENABLE_METRICS=true - - -KUBERNETES_CLUSTER_NAME="baklavastaging" -KUBERNETES_CLUSTER_ZONE="us-west1-a" -CLUSTER_DOMAIN_NAME="celo-testnet" - -TESTNET_PROJECT_NAME="celo-testnet-production" - -BLOCKSCOUT_DOCKER_IMAGE_TAG="0362f9f4d1d4842f27adb634d628f969f53c046d" -BLOCKSCOUT_DB_SUFFIX=2 - -CELOSTATS_SERVER_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/celostats-server" -CELOSTATS_SERVER_DOCKER_IMAGE_TAG="master" -CELOSTATS_FRONTEND_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/celostats-frontend" -CELOSTATS_FRONTEND_DOCKER_IMAGE_TAG="master" -CELOSTATS_TRUSTED_ADDRESSES="" -CELOSTATS_BANNED_ADDRESSES="" -CELOSTATS_RESERVED_ADDRESSES="" - -GETH_NODE_DOCKER_IMAGE_REPOSITORY="us.gcr.io/celo-org/geth" -GETH_NODE_DOCKER_IMAGE_TAG="1.7.0" - -GETH_BOOTNODE_DOCKER_IMAGE_REPOSITORY="us.gcr.io/celo-org/geth-all" -GETH_BOOTNODE_DOCKER_IMAGE_TAG="1.7.0" - -CELOTOOL_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/celo-monorepo" -CELOTOOL_DOCKER_IMAGE_TAG="celotool-4257fe61f91e935681f3a91bb4dcb44c8dd6df47" - -CELOCLI_STANDALONE_IMAGE_REPOSITORY="gcr.io/celo-testnet/celocli-standalone" -CELOCLI_STANDALONE_IMAGE_TAG="0.0.30-beta2" - -ORACLE_DOCKER_IMAGE_REPOSITORY="us-west1-docker.pkg.dev/celo-testnet-production/celo-oracle/celo-oracle" -ORACLE_DOCKER_IMAGE_TAG="1.0.7" - -# ---- Full Node Chain Restore ---- - -USE_GSTORAGE_DATA=true -GSTORAGE_DATA_BUCKET=celo-chain-backup/baklava - -# ---- Contexts ---- - -# each context should have its own environment variables, generally of the form -# _* -CONTEXTS=azure-oracle-westus2,azure-oracle-centralus,gcp-forno-europe-west1 - -# ---- Oracle Contexts ---- - -AZURE_ORACLE_WESTUS2_AZURE_SUBSCRIPTION_ID=7a6f5f20-bd43-4267-8c35-a734efca140c -AZURE_ORACLE_WESTUS2_AZURE_TENANT_ID=7cb7628a-e37c-4afb-8332-2029e418980e -AZURE_ORACLE_WESTUS2_AZURE_KUBERNETES_RESOURCE_GROUP=baklava-oracles-westus2 -AZURE_ORACLE_WESTUS2_AZURE_REGION_NAME=westus2 -AZURE_ORACLE_WESTUS2_KUBERNETES_CLUSTER_NAME=baklava-oracles-westus2 -# Format should be a comma-separated sequence of: -#
:: -AZURE_ORACLE_WESTUS2_CELOUSD_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x460b3f8d3c203363bb65b1a18d89d4ffb6b0c981:baklava-oracle2:baklava-oracles-westus2,0x3b522230c454ca9720665d66e6335a72327291e8:baklava-oracle3:baklava-oracles-westus2 -AZURE_ORACLE_WESTUS2_CELOEUR_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x042aC21b9CDA6171881135884DE16CF6aCa78375:baklava-celoeur-oracle2:baklava-oracles-westus2,0xc496d108C6781Fbc9967E48873Eac2eA14ca119a:baklava-celoeur-oracle3:baklava-oracles-westus2 -AZURE_ORACLE_WESTUS2_CELOBRL_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x86f9c87d13347e6041e75f3a18533e07d284c419:baklava-celobrl-oracle0:baklava-oracles-westus2,0x3ee0a85e7d8e9d06617986d40623b1493139c5ae:baklava-celobrl-oracle1:baklava-oracles-westus2 -AZURE_ORACLE_WESTUS2_USDCUSD_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x97ef27cf3ce65b2558161aeb1e3cff8b5f71fd04:baklava-usdcusd-oracle1:baklava-oracles-westus2,0x559702d23983eb29bcf30f2487d477945c0dbc6a:baklava-usdcusd-oracle3:baklava-oracles-westus2 -AZURE_ORACLE_WESTUS2_USDCBRL_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x8a2d375ae246e305c14c88e6687ff06acd66c9ba:baklava-brlusdc-oracle2:baklava-oracles-westus2,0x72434eca70d5544f8178c1a769762c8c1f0fd940:baklava-brlusdc-oracle5:baklava-oracles-westus2 -AZURE_ORACLE_WESTUS2_USDCEUR_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x99ce1e35574802e29644ee7a8284f9987fceee3d:baklava-eurusdc-oracle6:baklava-oracles-westus2,0x4c37e2cc2e9105984fef866a3f06aa953cc660d1:baklava-eurusdc-oracle7:baklava-oracles-westus2 -AZURE_ORACLE_WESTUS2_EUROCEUR_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x6866e306b32acae7310d3b87dd53fc948f0e0629:baklava-euroceur-oracle2:baklava-oracles-westus2,0xe33502b13be6e0444a08de933faa24a59ae9b585:baklava-euroceur-oracle3:baklava-oracles-westus2 -AZURE_ORACLE_WESTUS2_CELOXOF_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x96eda2cad69c8cd1daeb80da86d24825f45f46b7:baklava-celoxof-oracle2,0x4e9d441fd1c77222395a1853d851fea8a0e3aed8:baklava-celoxof-oracle3 -AZURE_ORACLE_WESTUS2_EURXOF_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x7fe5f297dd812ca21e7bf1cbf145a0b59227b35f:baklava-eurxof-oracle2,0x2addc69c2ce3a9d93a8291419319bf7f0a2c6c82:baklava-eurxof-oracle3 -AZURE_ORACLE_WESTUS2_EUROCXOF_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x729e058e97c099c79af674bbe2f687171432dd17:baklava-eurocxof-oracle2,0xd226aa9ee80ee282339c1ae69f3f811dbe5d895a:baklava-eurocxof-oracle4 -AZURE_ORACLE_WESTUS2_FULL_NODES_COUNT=2 -AZURE_ORACLE_WESTUS2_FULL_NODES_ROLLING_UPDATE_PARTITION=0 -AZURE_ORACLE_WESTUS2_FULL_NODES_DISK_SIZE=30 -AZURE_ORACLE_WESTUS2_FULL_NODES_RPC_API_METHODS="eth,net,rpc,web3" -AZURE_ORACLE_WESTUS2_FULL_NODES_GETH_GC_MODE="full" -AZURE_ORACLE_WESTUS2_FULL_NODES_USE_GSTORAGE_DATA=false -AZURE_ORACLE_WESTUS2_FULL_NODES_WS_PORT="8546" -AZURE_ORACLE_WESTUS2_PROM_SIDECAR_DISABLED="true" - -AZURE_ORACLE_CENTRALUS_AZURE_SUBSCRIPTION_ID=7a6f5f20-bd43-4267-8c35-a734efca140c -AZURE_ORACLE_CENTRALUS_AZURE_TENANT_ID=7cb7628a-e37c-4afb-8332-2029e418980e -AZURE_ORACLE_CENTRALUS_AZURE_KUBERNETES_RESOURCE_GROUP=baklava-oracles-centralus -AZURE_ORACLE_CENTRALUS_AZURE_REGION_NAME=centralus -AZURE_ORACLE_CENTRALUS_KUBERNETES_CLUSTER_NAME=baklava-oracles-centralus -# Format should be a comma-separated sequence of: -#
:: -AZURE_ORACLE_CENTRALUS_CELOUSD_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x02b1d1bea682fcab4448c0820f5db409cce4f702:baklava-oracle7:baklava-oracles-centralus,0xe90f891710f625f18ecbf1e02efb4fd1ab236a10:baklava-oracle8:baklava-oracles-centralus -AZURE_ORACLE_CENTRALUS_CELOEUR_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x4Ab2B594f08403b6324Cb0B172e332d8a08f1d5a:baklava-celoeur-oracle7:baklava-oracles-centralus,0x21d66472604A931211379A32710D26AFA203D190:baklava-celoeur-oracle8:baklava-oracles-centralus -AZURE_ORACLE_CENTRALUS_CELOBRL_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0xe467003845bdcbef710192d86263716815ab39f6:baklava-celobrl-oracle2:baklava-oracles-centralus,0x4b7f9e7e18230a271109f67b60a70fb3b4d0268a:baklava-celobrl-oracle3:baklava-oracles-centralus -AZURE_ORACLE_CENTRALUS_USDCUSD_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x6a0e5d8a496feb59464028250c88a08341ea0831:baklava-usdcusd-oracle0:baklava-oracles-centralus,0xb15833400aecc72cb759d4e57a3a5a9c2963a5c5:baklava-usdcusd-oracle2:baklava-oracles-centralus -AZURE_ORACLE_CENTRALUS_USDCBRL_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0xa326d557b79422952d708d4eea8523d29b7174ec:baklava-brlusdc-oracle0:baklava-oracles-centralus,0xe73b1f39d1289e608df9a055c459b909f4bc1592:baklava-brlusdc-oracle1:baklava-oracles-centralus -AZURE_ORACLE_CENTRALUS_USDCEUR_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0xa6a5ae0c1c6b0ed52f2c6bb5666b61cfa86ac3ae:baklava-eurusdc-oracle4:baklava-oracles-centralus,0x2679be4034f47219bf9dfcbfb55bad60fe741315:baklava-eurusdc-oracle5:baklava-oracles-centralus -AZURE_ORACLE_CENTRALUS_EUROCEUR_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x9a0613e8a1ff6cfd72ab692e6b450fbf02deba81:baklava-euroceur-oracle0:baklava-oracles-centralus,0xbe4bbd15177e2857c7c3297da12331033eeacd93:baklava-euroceur-oracle1:baklava-oracles-centralus -AZURE_ORACLE_CENTRALUS_CELOXOF_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0xd056a29e86161a34692c34f4c95933b59de077dc:baklava-celoxof-oracle0,0x5ad07f89176298ae3a0f3d20d0b4a756307d46e7:baklava-celoxof-oracle1 -AZURE_ORACLE_CENTRALUS_EURXOF_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0xa4a46db00840e6525ffe79aee5990abaebb7479d:baklava-eurxof-oracle0,0x6e537c9462ed968ff08eab430c5f8c11eab7df1a:baklava-eurxof-oracle1 -AZURE_ORACLE_CENTRALUS_EUROCXOF_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x1a637c38671512866317475d19df5f55b0802276:baklava-eurocxof-oracle0,0x8589f0bb307581b96877f9e1a5ce3fcb05127fd0:baklava-eurocxof-oracle1 -AZURE_ORACLE_CENTRALUS_FULL_NODES_COUNT=2 -AZURE_ORACLE_CENTRALUS_FULL_NODES_ROLLING_UPDATE_PARTITION=0 -AZURE_ORACLE_CENTRALUS_FULL_NODES_DISK_SIZE=30 -AZURE_ORACLE_CENTRALUS_FULL_NODES_RPC_API_METHODS="eth,net,rpc,web3" -AZURE_ORACLE_CENTRALUS_FULL_NODES_GETH_GC_MODE="full" -AZURE_ORACLE_CENTRALUS_FULL_NODES_USE_GSTORAGE_DATA=false -AZURE_ORACLE_CENTRALUS_FULL_NODES_WS_PORT="8546" -AZURE_ORACLE_CENTRALUS_PROM_SIDECAR_DISABLED="true" - -# ---- Forno ---- - -# ---- General Forno ---- - -# A list of every context that forno will use. -FORNO_FULL_NODE_CONTEXTS=gcp-forno-europe-west1 -# A list of domains to provision the SSL certificate for -FORNO_DOMAINS=baklava-forno-k8s.celo-testnet.org -# All forno clusters must be in this VPC -FORNO_VPC_NETWORK_NAME=baklava-network -FORNO_BANNED_CIDR="255.255.255.255/32" - -# ---- Forno Contexts ---- - -GCP_FORNO_EUROPE_WEST1_GCP_PROJECT_NAME=celo-testnet-production -GCP_FORNO_EUROPE_WEST1_GCP_ZONE=europe-west1-b -GCP_FORNO_EUROPE_WEST1_KUBERNETES_CLUSTER_NAME=baklava-europe-west1 -GCP_FORNO_EUROPE_WEST1_FULL_NODES_COUNT=2 -GCP_FORNO_EUROPE_WEST1_FULL_NODES_ROLLING_UPDATE_PARTITION=0 -GCP_FORNO_EUROPE_WEST1_FULL_NODES_DISK_SIZE=100 -# NOTE: If these fullnodes are used for static nodes, changing this will result -# in the full nodes having a different nodekey -GCP_FORNO_EUROPE_WEST1_FULL_NODES_NODEKEY_DERIVATION_STRING=GCP_FORNO_EUROPE_WEST1 -# suffix of the static nodes file, e.g. `.` -GCP_FORNO_EUROPE_WEST1_FULL_NODES_STATIC_NODES_FILE_SUFFIX=gcp-europe-west1 -GCP_FORNO_EUROPE_WEST1_FULL_NODES_RPC_API_METHODS="eth,net,rpc,web3" -GCP_FORNO_EUROPE_WEST1_FULL_NODES_GETH_GC_MODE="full" -GCP_FORNO_EUROPE_WEST1_FULL_NODES_USE_GSTORAGE_DATA=false -GCP_FORNO_EUROPE_WEST1_FULL_NODES_WS_PORT="8546" -GCP_FORNO_EUROPE_WEST1_PROM_SIDECAR_DISABLED="true" - -TRANSACTION_METRICS_EXPORTER_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/celo-monorepo" -TRANSACTION_METRICS_EXPORTER_DOCKER_IMAGE_TAG="transaction-metrics-exporter-dc5e5dfa07231a4ff4664816a95eae606293eae9" - -# Genesis Vars -NETWORK_ID=62320 -CONSENSUS_TYPE="istanbul" -BLOCK_TIME=5 -EPOCH=17280 -LOOKBACK=12 -ISTANBUL_REQUEST_TIMEOUT_MS=10000 - -# the number of load test clients that will be given funds in the genesis & migrations -LOAD_TEST_CLIENTS=20 -# every 7.2 seconds, so that 500 transactions are sent by a client every hour -# to simulate 10,000 total transactions per hour -LOAD_TEST_TX_DELAY_MS=7200 - -# the amount in cUSD wei to give faucet, load test, and attestation bot accounts -FAUCET_CUSD_WEI=60000000000000000000000 - -# format: <# of validators>:,<# of validators>:;... -# For vm-based testnets: The n proxied validators have to be the n first validators. Only indicate in the list the validators with proxy. -# Example: For a 10 validator testnet, 2:3,2:2,2:1 will result in Validator 0-1 with 3 proxies, 2-3 with 2 proxies, 4-5 with 1 proxy, and 6-9 with 0 proxies -VALIDATORS=6 -VALIDATOR_PROXY_COUNTS=2:0,2:1,1:2,1:3 -SECONDARIES=5 -ELECTION_MIN_VALIDATORS=20 -# TX_NODES are used for forno -TX_NODES=3 - -# Nodes whose RPC ports are only internally exposed. Used bu Blockscout and other internal services. -PRIVATE_TX_NODES=2 - -STATIC_IPS_FOR_GETH_NODES=true -# Whether tx_nodes/validators stateful set should use ssd persistent disks -GETH_NODES_SSD_DISKS=true -# Used for validators, proxies, and tx_nodes -NODE_DISK_SIZE_GB=100 -# Used for private tx_nodes (gcmode archive) -PRIVATE_NODE_DISK_SIZE_GB=100 -IN_MEMORY_DISCOVERY_TABLE=false -# PING_IP_FROM_PACKET=false - -# Testnet vars -CLUSTER_CREATION_FLAGS="--enable-autoscaling --min-nodes 3 --max-nodes 8 --machine-type=n1-standard-4" - -GETH_NODE_CPU_REQUEST=2 -GETH_NODE_MEMORY_REQUEST=4Gi - -VERIFICATION_POOL_URL="https://us-central1-celo-testnet.cloudfunctions.net/handleVerificationRequestbaklava/v0.1/sms/" -VERIFICATION_REWARDS_URL="https://us-central1-celo-testnet.cloudfunctions.net/handleVerificationRequestbaklava/v0.1/rewards/" - -# Disable the sidecar that forwards the metrics to stackdriver -PROMETHEUS_DISABLE_STACKDRIVER_SIDECAR="true" - -MOBILE_WALLET_PLAYSTORE_LINK="https://play.google.com/apps/internaltest/4700990475000634666" - -# Number of gold-holding bots that vote for validator groups -VOTING_BOTS=100 -# 10,000 CG -VOTING_BOT_BALANCE=10000000000000000000000 - -# Probability that a given bot account will participate in the current epoch's voting -VOTING_BOT_WAKE_PROBABILITY=0 - -# Baseline probability of changing vote once woken. If the group that this bot account -# has currently voted for is 1, this is the probability the bot will change their vote -VOTING_BOT_CHANGE_BASELINE=0 - -# The probability that when choosing a new group to vote for, it will choose a never-elected group -# Should be in the range of 0 to 1. Lower values bias towards incumbency. Higher values bias -# towards novelty. -VOTING_BOT_EXPLORE_PROBABILITY=0.6 - -# This value is used to determine how heavily a group's score weigh in the bot's voting decision -# Should be a positive number. 1 is a linear relationship. Higher values increase the separation -# among high scores. Less than 1 has a steep drop-off for low-scoring groups. -VOTING_BOT_SCORE_SENSITIVITY=1 - -# Schedule for the voting bot process, deployed via celotool, expressed in crontab syntax -# Minimum epoch length is 1 hour. This cron schedule is "every hour at minute 1", in order -# to run once an epoch. -# Notes: -# - if an epoch takes longer, this will occasionally run twice in an epoch -# - Running on minute 1 is arbitrary. This could be any value from 0-59. -VOTING_BOT_CRON_SCHEDULE="1 * * * *" - -# For WalletConnect relay -WALLET_CONNECT_IMAGE_REPOSITORY = 'us.gcr.io/celo-testnet/walletconnect' -WALLET_CONNECT_IMAGE_TAG = '1472bcaad57e3746498f7a661c42ff5cf9acaf5a' -WALLET_CONNECT_REDIS_CLUSTER_ENABLED = false -WALLET_CONNECT_REDIS_CLUSTER_USEPASSWORD = false diff --git a/.env.mnemonic.alfajores.enc b/.env.mnemonic.alfajores.enc deleted file mode 100644 index dc214d6f4..000000000 Binary files a/.env.mnemonic.alfajores.enc and /dev/null differ diff --git a/.env.mnemonic.baklava.enc b/.env.mnemonic.baklava.enc deleted file mode 100644 index 4096501b0..000000000 Binary files a/.env.mnemonic.baklava.enc and /dev/null differ diff --git a/.env.mnemonic.enc b/.env.mnemonic.enc deleted file mode 100644 index f2d0ca897..000000000 Binary files a/.env.mnemonic.enc and /dev/null differ diff --git a/.env.mnemonic.rc1.enc b/.env.mnemonic.rc1.enc deleted file mode 100644 index 37abb5321..000000000 Binary files a/.env.mnemonic.rc1.enc and /dev/null differ diff --git a/.env.oracledev b/.env.oracledev deleted file mode 100644 index 2cda4367b..000000000 --- a/.env.oracledev +++ /dev/null @@ -1,142 +0,0 @@ -ORACLE_DOCKER_IMAGE_REPOSITORY="celotestnet.azurecr.io/testnet/oracle" -ORACLE_DOCKER_IMAGE_TAG="c7215fcbeccc0c61b306fbd0503a67bd0cf509de" - -ORACLE_UNUSED_ORACLE_ADDRESSES= - -# each context should have its own environment variables, generally of the form -# _* -CONTEXTS=azure-eastus,gcp-test,gcp-test-asia - -FORNO_FULL_NODE_CONTEXTS=gcp-test,gcp-test-asia -FORNO_DOMAINS=oracledev-forno.celo-networks-dev.org. -# all clusters must be in this VPC -FORNO_VPC_NETWORK_NAME=default - -AZURE_EASTUS_AZURE_SUBSCRIPTION_ID=97e2b592-255b-4f92-bce0-127257163c36 -AZURE_EASTUS_AZURE_TENANT_ID=7cb7628a-e37c-4afb-8332-2029e418980e -AZURE_EASTUS_AZURE_KUBERNETES_RESOURCE_GROUP=testnet-oracle-eastus -AZURE_EASTUS_KUBERNETES_CLUSTER_NAME=testnet-oracle-eastus -# Format should be a comma-separated sequence of: -#
:: -AZURE_EASTUS_CELOUSD_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x21860ca3a0a6f7e450b8f24bd00eac7ba766b85e:testnet-oracle-eastus,0xfd3738e5e0a020614a9e5253078dda491e77031c:testnet-oracle-eastus -# AZURE_EASTUS_CELOUSD_ORACLE_ADDRESSES_FROM_MNEMONIC_COUNT= -AZURE_EASTUS_FULL_NODES_COUNT=2 -AZURE_EASTUS_FULL_NODES_DISK_SIZE=10 - -# Format should be a comma-separated sequence of: -#
:: -GCP_TEST_GCP_PROJECT_NAME=celo-testnet -GCP_TEST_GCP_ZONE=us-west4-a -GCP_TEST_KUBERNETES_CLUSTER_NAME=federated-dev-us-west4-a -GCP_TEST_FULL_NODES_COUNT=1 -GCP_TEST_FULL_NODES_DISK_SIZE=10 -GCP_TEST_FULL_NODES_STATIC_NODES_FILE_SUFFIX=gcp-test - -GCP_TEST_ASIA_GCP_PROJECT_NAME=celo-testnet -GCP_TEST_ASIA_GCP_ZONE=asia-northeast2-a -GCP_TEST_ASIA_KUBERNETES_CLUSTER_NAME=federated-dev-asia-northeast2-a -GCP_TEST_ASIA_FULL_NODES_STATIC_NODES_FILE_SUFFIX=gcp-test-asia -GCP_TEST_ASIA_FULL_NODES_COUNT=1 -GCP_TEST_ASIA_FULL_NODES_DISK_SIZE=10 - -# ---- General ---- - -ENV_TYPE="development" -CLUSTER_DOMAIN_NAME="celo-networks-dev" -TESTNET_PROJECT_NAME="celo-testnet" -CLUSTER_DOMAIN_NAME="celo-networks-dev" - -# ---- Kubernetes ---- - -KUBERNETES_CLUSTER_NAME="celo-networks-dev" -KUBERNETES_CLUSTER_ZONE="us-west1-a" -CLUSTER_CREATION_FLAGS="--enable-autoscaling --min-nodes 3 --max-nodes 8 --machine-type=n1-standard-4" - -# ---- VM ---- - - -# ---- Blockscout ---- - -BLOCKSCOUT_DOCKER_IMAGE_TAG="ad86714d629c01272e0651dec1fb6a968c3cec71" -BLOCKSCOUT_DB_SUFFIX="-2" - -# ---- Geth ---- - -GETH_NODE_DOCKER_IMAGE_REPOSITORY="us.gcr.io/celo-testnet/geth" -# When upgrading change this to latest commit hash from the master of the geth repo -# `geth $ git show | head -n 1` -GETH_NODE_DOCKER_IMAGE_TAG="8a44c2cd92200bdffce595c7558e84a39ea2bc15" - -GETH_VERBOSITY=2 - -GETH_BOOTNODE_DOCKER_IMAGE_REPOSITORY="us.gcr.io/celo-testnet/geth-all" -# When upgrading change this to latest commit hash from the master of the geth repo -# `geth $ git show | head -n 1` -GETH_BOOTNODE_DOCKER_IMAGE_TAG="8a44c2cd92200bdffce595c7558e84a39ea2bc15" - -# ---- Celotool ---- - -CELOTOOL_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/celo-monorepo" -CELOTOOL_DOCKER_IMAGE_TAG="celotool-4257fe61f91e935681f3a91bb4dcb44c8dd6df47" - -# ---- Transaction Metrics Exporter ---- - -TRANSACTION_METRICS_EXPORTER_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/celo-monorepo" -TRANSACTION_METRICS_EXPORTER_DOCKER_IMAGE_TAG="transaction-metrics-exporter-8e69cf86010b62e283d5f9285f181fca5483733e" - -# ---- Genesis Vars ---- -NETWORK_ID=1101 -CONSENSUS_TYPE="istanbul" -PREDEPLOYED_CONTRACTS="REGISTRY" -BLOCK_TIME=5 -EPOCH=720 - -# ---- Network Vars ---- -VALIDATORS=2 -PROXIED_VALIDATORS=0 -TX_NODES=1 -# Nodes whose RPC ports are only internally exposed -PRIVATE_TX_NODES=1 -STATIC_IPS_FOR_GETH_NODES=false -PING_IP_FROM_PACKET=true -IN_MEMORY_DISCOVERY_TABLE=false -ISTANBUL_REQUEST_TIMEOUT_MS=3000 -# Used for validators, proxies, and tx_nodes -NODE_DISK_SIZE_GB=10 -# Used for private tx_nodes (gcmode archive) -PRIVATE_NODE_DISK_SIZE_GB=10 -ADMIN_RPC_ENABLED=false -LOAD_TEST_CLIENTS=100 -# every 36 seconds, so that 100 transactions are sent by a client every hour -LOAD_TEST_TX_DELAY_MS=36000 - -GETH_NODE_CPU_REQUEST=400m -GETH_NODE_MEMORY_REQUEST=1.75G - -VERIFICATION_POOL_URL="https://us-central1-celo-testnet.cloudfunctions.net/handleVerificationRequesttrevor1/v0.1/sms/" -VERIFICATION_REWARDS_URL="https://us-central1-celo-testnet.cloudfunctions.net/handleVerificationRequesttrevor1/v0.1/rewards/" - -MOBILE_WALLET_PLAYSTORE_LINK="https://play.google.com/apps/internaltest/4700990475000634666" - -NOTIFICATION_SERVICE_FIREBASE_DB="https://console.firebase.google.com/u/0/project/celo-org-mobile/database/celo-org-mobile-int/data" - -AUCTION_CRON_SPEC="*/5 * * * *" - -SMS_RETRIEVER_HASH_CODE=l5k6LvdPDXS -# empty string is false for helm -GETH_NODES_BACKUP_CRONJOB_ENABLED= -CONTRACT_CRONJOBS_ENABLED= - -# Schedule for an oracle deployed via celotool, expressed in crontab syntax -# This schedule is "every 5th minute" -MOCK_ORACLE_CRON_SCHEDULE="*/5 * * * *" - -MOCK_ORACLE_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/oracle" -MOCK_ORACLE_DOCKER_IMAGE_TAG="baklava" - -# The number of oracles to add during contract migrations. -# Their keys/addresses are generated using the mnemonic -ORACLES=10 - -CELOCLI_STANDALONE_IMAGE_REPOSITORY="gcr.io/celo-testnet/celocli-standalone" -CELOCLI_STANDALONE_IMAGE_TAG="0.0.30-beta2" diff --git a/.env.rc1 b/.env.rc1 deleted file mode 100644 index 4194f61f6..000000000 --- a/.env.rc1 +++ /dev/null @@ -1,473 +0,0 @@ -# Don't use "//" for comments in this file. -# This file is meant to be executed as a bash script for testing. -ENV_TYPE="production" - -GETH_VERBOSITY=2 -GETH_ENABLE_METRICS=false - -VM_BASED=true - -KUBERNETES_CLUSTER_NAME="mainnet" -KUBERNETES_CLUSTER_ZONE="us-west1-a" -CLUSTER_DOMAIN_NAME="celo-testnet" - -TESTNET_PROJECT_NAME="celo-testnet-production" - -BLOCKSCOUT_DOCKER_IMAGE_TAG="0362f9f4d1d4842f27adb634d628f969f53c046d" -BLOCKSCOUT_DB_SUFFIX=3 - -CELOSTATS_SERVER_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/celostats-server" -CELOSTATS_SERVER_DOCKER_IMAGE_TAG="master" -CELOSTATS_FRONTEND_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/celostats-frontend" -CELOSTATS_FRONTEND_DOCKER_IMAGE_TAG="master" -CELOSTATS_TRUSTED_ADDRESSES="" -CELOSTATS_BANNED_ADDRESSES="" -CELOSTATS_RESERVED_ADDRESSES="" - -GETH_NODE_DOCKER_IMAGE_REPOSITORY="us.gcr.io/celo-org/geth" -# When upgrading change this to latest commit hash from the master of the geth repo -# `geth $ git show | head -n 1` -GETH_NODE_DOCKER_IMAGE_TAG="1.7.0" - -GETH_BOOTNODE_DOCKER_IMAGE_REPOSITORY="us.gcr.io/celo-org/geth-all" -# When upgrading change this to latest commit hash from the master of the geth repo -# `geth $ git show | head -n 1` -GETH_BOOTNODE_DOCKER_IMAGE_TAG="1.7.0" - -CELOTOOL_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/celo-monorepo" -CELOTOOL_DOCKER_IMAGE_TAG="celotool-4257fe61f91e935681f3a91bb4dcb44c8dd6df47" - -CELOCLI_STANDALONE_IMAGE_REPOSITORY="gcr.io/celo-testnet/celocli-standalone" -CELOCLI_STANDALONE_IMAGE_TAG="0.0.42" - -# Schedule for an oracle deployed via celotool, expressed in crontab syntax -# This schedule is "every 5th minute" -MOCK_ORACLE_CRON_SCHEDULE="*/5 * * * *" - -ORACLE_DOCKER_IMAGE_REPOSITORY="us-west1-docker.pkg.dev/celo-testnet-production/celo-oracle/celo-oracle" -ORACLE_DOCKER_IMAGE_TAG="1.0.6" - -ORACLE_UNUSED_ORACLE_ADDRESSES=0xB93Fe7906ea4221b3fbe23412D18Ab1B07FE2F71,0x8d25D74E43789079Ef3C6B965c3D22b63A1233aC,0xCD88Cc79342a7cFE78E91FAa173eC87704bDcA9a,0x5091110175318A2A8aF88309D1648c1D84d31B29,0xBBd6e54Af7A5722f42461C6313F37Bd50729F195,0xE23a4c6615669526Ab58E9c37088bee4eD2b2dEE - -# ---- Full Node Chain Restore ---- - -USE_GSTORAGE_DATA=true -GSTORAGE_DATA_BUCKET=celo-chain-backup/mainnet - -# ---- Contexts ---- - -# A list of every valid context. Must start with one of: gcp,azure -# each context should have its own environment variables, generally of the form -# _* -CONTEXTS=azure-oracle-westus,azure-oracle-westeurope,azure-oracle-eastus2,gcp-forno-us-west1,gcp-forno-us-east1,gcp-forno-asia-east1,gcp-forno-europe-west1,gcp-forno-southamerica-east1,azure-odis-westus2-a,azure-odis-eastasia-a,azure-odis-westeurope-a,azure-odis-brazilsouth-a,gcp-private-txnodes - -# ---- Oracle Contexts ---- - -AZURE_ORACLE_WESTUS_AZURE_SUBSCRIPTION_ID=7a6f5f20-bd43-4267-8c35-a734efca140c -AZURE_ORACLE_WESTUS_AZURE_TENANT_ID=7cb7628a-e37c-4afb-8332-2029e418980e -AZURE_ORACLE_WESTUS_AZURE_REGION_NAME=wus -AZURE_ORACLE_WESTUS_AZURE_KUBERNETES_RESOURCE_GROUP=mainnet-oracles-westus2 -AZURE_ORACLE_WESTUS_KUBERNETES_CLUSTER_NAME=mainnet-oracles-westus2v1 -# Format should be a comma-separated sequence of: -#
:: -AZURE_ORACLE_WESTUS_CELOUSD_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x0aee051be85ba9c7c1bc635fb76b52039341ab26:mainnet-oracle0:mainnet-oracles-westus2,0xd3405621f6cdcd95519a79d37f91c78e7c79cefa:mainnet-oracle1:mainnet-oracles-westus2,0xe037f31121f3a96c0cc49d0cf55b2f5d6deff19e:mainnet-oracle2:mainnet-oracles-westus2,0x12bad172b47287a754048f0d294221a499d1690f:mainnet-oracle3:mainnet-oracles-westus2,0xacad5b2913e21ccc073b80e431fec651cd8231c6:mainnet-oracle4:mainnet-oracles-westus2 -AZURE_ORACLE_WESTUS_CELOEUR_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0xb8bDBfdd591a5be5980983A7ba1710a5F46f42B5:mainnet-eur-oracle-wus2:mainnet-oracles-westus2,0x929Ad7f2b781CE830014E824CA2eF0b7b8de87C2:mainnet-eur-oracle-wus3:mainnet-oracles-westus2,0xCCC0B54edD8dAe3c15b5C002dd5d348495d4f7fe:mainnet-eur-oracle-wus4:mainnet-oracles-westus2 -AZURE_ORACLE_WESTUS_CELOBRL_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x57d8a7bf9e7f4113c49e077b140fd8e1d7f78a76:mainnet-brl-oracle-wus0:mainnet-oracles-westus2,0x1299dd007cd5120262e546dca893e30d1cff8a10:mainnet-brl-oracle-wus1:mainnet-oracles-westus2,0x116951e440aee97a328614f9937710c9bb2f0839:mainnet-brl-oracle-wus4:mainnet-oracles-westus2 -AZURE_ORACLE_WESTUS_USDCUSD_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x2986c21824c9b804d170270a316ceb07149f79c5:mainnet-usdcusd-wus0,0x09e2e47bb5df7b3464407746970a65c7b02883b3:mainnet-usdcusd-wus1,0xd5e7454932f6e853af849f70044570b62ca2596e:mainnet-usdcusd-wus2,0xfe3276b7142dee2cda34b1d14852eb32f436483d:mainnet-usdcusd-wus3 -AZURE_ORACLE_WESTUS_USDCEUR_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0xeccd1e9439094d025ac7d08d16b0bfe0da3bea53:mainnet-usdceur-wus0,0x9b242d2bd848fc92060ca7546033c3af352583d2:mainnet-usdceur-wus1,0x905ab001a9199d45c3f5c7b055b65ace5fc7d70a:mainnet-usdceur-wus2,0xdf5dd31d8f78520185d6a9fb0498c4bbddfe0708:mainnet-usdceur-wus3 -AZURE_ORACLE_WESTUS_USDCBRL_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x8dba01f832c7b0bb5f0bad4efe181cc07f8b322e:mainnet-usdcbrl-wus0,0xffb417d009d09bd1140244e70babbaa52d69ec84:mainnet-usdcbrl-wus1,0x5f755b8350a2e6b8b042cb3e052580e4c5b0ac35:mainnet-usdcbrl-wus2,0x8e1349b48ee82ef5437c912662e6640f3590c6f9:mainnet-usdcbrl-wus3 -AZURE_ORACLE_WESTUS_EUROCEUR_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x6e7c84f83778569016ea0a7f6f119d6b779eed17:mainnet-euroceur-wus0,0xf96bf6c3b9ea73150f0d7f452fba685ff456c322:mainnet-euroceur-wus1,0xc5bf0748538f8673691bc9c8e4eae386d5987559:mainnet-euroceur-wus2,0xe868cd23a3941dfbab10597b103313706a027191:mainnet-euroceur-wus3 -AZURE_ORACLE_WESTUS_CELOXOF_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0xce696d465dde582095fce8b67e1a31ceb45ad922:mainnet-celoxof-wus0,0xbc211b8dfecdd5784f9c419ce64f7de1377bae88:mainnet-celoxof-wus1,0xc659ab5c049b726c2945a8a44b783ce6afbd2ceb:mainnet-celoxof-wus2,0x9094bf2b2eb028c6fcc56e7d46ea28bb6e03c9a5:mainnet-celoxof-wus3,0xb947c54be882314623ee3d74684d0d785dd50335:mainnet-celoxof-wus4 -AZURE_ORACLE_WESTUS_EURXOF_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x6a033b7217fbae843a3ffc9783ef9f87dd3a1c04:mainnet-eurxof-wus0,0x8a164c0523bbd7ec70172807723cca9a948858bb:mainnet-eurxof-wus1,0xd0066f198ed7f8dc3684ff3ac77511ef58a9aed3:mainnet-eurxof-wus2,0x441061f8b1f8ee2722d3608bfa0b5c4c14dee813:mainnet-eurxof-wus3,0x87089ec6adbf3c994ae7c47d3aa7d4fc104d0422:mainnet-eurxof-wus4 -AZURE_ORACLE_WESTUS_EUROCXOF_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0xc5a86597d514b423579684cdf9f49b6df37e3689:mainnet-eurocxof-wus0,0x8e1423ca0bcb15093f52d1d07675e0aa04e3da75:mainnet-eurocxof-wus1,0xa47e6a8a7db5ee22b5293704a4f0f5f8fdaab06f:mainnet-eurocxof-wus2,0x77d148efdd40202d0eec787073a70c7f6bc9c485:mainnet-eurocxof-wus3,0xfef8748fd3f039fb8cfa77c7744b171f4396659c:mainnet-eurocxof-wus4 -AZURE_ORACLE_WESTUS_FULL_NODES_COUNT=5 -AZURE_ORACLE_WESTUS_FULL_NODES_ROLLING_UPDATE_PARTITION=0 -AZURE_ORACLE_WESTUS_FULL_NODES_DISK_SIZE=100 -AZURE_ORACLE_WESTUS_FULL_NODES_RPC_API_METHODS="eth,net,rpc,web3" -AZURE_ORACLE_WESTUS_FULL_NODES_GETH_GC_MODE="full" -AZURE_ORACLE_WESTUS_FULL_NODES_USE_GSTORAGE_DATA=false -AZURE_ORACLE_WESTUS_FULL_NODES_WS_PORT="8546" -AZURE_ORACLE_WESTUS_PROM_SIDECAR_DISABLED="true" - -AZURE_ORACLE_WESTEUROPE_AZURE_SUBSCRIPTION_ID=7a6f5f20-bd43-4267-8c35-a734efca140c -AZURE_ORACLE_WESTEUROPE_AZURE_TENANT_ID=7cb7628a-e37c-4afb-8332-2029e418980e -AZURE_ORACLE_WESTEUROPE_AZURE_REGION_NAME=weu -AZURE_ORACLE_WESTEUROPE_AZURE_KUBERNETES_RESOURCE_GROUP=mainnet-oracles-westeurope -AZURE_ORACLE_WESTEUROPE_KUBERNETES_CLUSTER_NAME=mainnet-oracles-westeurope -# Format should be a comma-separated sequence of: -#
:: -AZURE_ORACLE_WESTEUROPE_CELOUSD_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0xfe9925e6ae9c4cd50ae471b90766aaef37ad307e:mainnet-oracle-eu0:mainnet-oracles-westeurope,0x641c6466dae2c0b1f1f4f9c547bc3f54f4744a1d:mainnet-oracle-eu1:mainnet-oracles-westeurope,0x75becd8e400552bac29cbe0534d8c7d6cba49979:mainnet-oracle-eu2:mainnet-oracles-westeurope -AZURE_ORACLE_WESTEUROPE_CELOEUR_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x87C45738DAd8Dc3D2b1cCe779E0766329cc408C6:mainnet-eur-oracle-weu0:mainnet-oracles-westeurope,0xeF1E143C554EFC43B0537Af00Ac27C828dE6cF8D:mainnet-eur-oracle-weu1:mainnet-oracles-westeurope,0xF4B4AA107F30206EA019DE145A9b778a220f9fc0:mainnet-eur-oracle-weu2:mainnet-oracles-westeurope,0x24c303e6395DD19806F739619960A311764e3F40:mainnet-eur-oracle-weu3:mainnet-oracles-westeurope,0xDA413875FB45E5905950Bc08a908ebD246Ee6581:mainnet-eur-oracle-weu5:mainnet-oracles-westeurope -AZURE_ORACLE_WESTEUROPE_CELOBRL_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x3b91bbb873f3b979bd6671dc018d5fc1848882dd:mainnet-brl-oracle-weu0:mainnet-oracles-westeurope,0xc3994b2af0e82490e432d49e9f2246cdfd84da8f:mainnet-brl-oracle-weu1:mainnet-oracles-westeurope,0x9b376b33c33325332df8c6ca951a9896889a6d1e:mainnet-brl-oracle-weu2:mainnet-oracles-westeurope,0x554ba7f4d200c7b233b93b7f2223bc1ea7c467fd:mainnet-brl-oracle-weu3:mainnet-oracles-westeurope,0x535cea1834d6b52e4e9724642fdd7008f569ba5c:mainnet-brl-oracle-weu4:mainnet-oracles-westeurope -AZURE_ORACLE_WESTEUROPE_USDCUSD_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x477185291403ca2ed5f56d59ed0d568a16222013:mainnet-usdcusd-weu0,0x9a0a52d483c62df76d54f41ab3283cc7cb41ba91:mainnet-usdcusd-weu1,0x2ddb86898a2c2c884fc5cc3ca344898b0170a00d:mainnet-usdcusd-weu2,0x79be0a692e3a4bcd22b96c3e93a108b485becbb2:mainnet-usdcusd-weu3 -AZURE_ORACLE_WESTEUROPE_USDCEUR_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x0781f530100e619936f5b427263441cb0414f885:mainnet-usdceur-weu0,0x55de75fd0c2b37987757172fef7ba2ea935d284d:mainnet-usdceur-weu1,0xdc0c15fa73b13b2e74cd3eced23d8826569904c5:mainnet-usdceur-weu2,0x9048872f739cebbe72825763a1b72064c4df8f1f:mainnet-usdceur-weu3 -AZURE_ORACLE_WESTEUROPE_USDCBRL_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x42b813b9ff8ce8f4837accea26bedda20d7c4982:mainnet-usdcbrl-weu0,0x09208127500963ee1c3af88bfbb3ef0cd34d6eb0:mainnet-usdcbrl-weu1,0xa8f5be092a8452eab98ed1c220d642114bb2731e:mainnet-usdcbrl-weu2,0xfd265c994a5a9c2847fe03a5e878648963f53a37:mainnet-usdcbrl-weu3 -AZURE_ORACLE_WESTEUROPE_EUROCEUR_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0xa633c79ac2c6881c0898b2b417a3aecda6f9eb10:mainnet-euroceur-weu0,0xbc32b5e6682bd7b64e52bdceead83f597ed0fd77:mainnet-euroceur-weu1,0x110d08157ed0c525f7fd983a857180583767cbcf:mainnet-euroceur-weu2,0xa8c15faf676df18566c4b8c4c653e5f992e687bb:mainnet-euroceur-weu3 -AZURE_ORACLE_WESTEUROPE_CELOXOF_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x4d89a0c95de82ae78c42fad4f8d3f87c4495fd37:mainnet-celoxof-weu0,0xa97dbefac6026f93cc5714c4c150b7466e9502ef:mainnet-celoxof-weu1,0x676931c73c8d6b09b0c192baf821e3fd2d693750:mainnet-celoxof-weu2,0xfb8f294c8cd98cf059672c1a6153f85555f10a90:mainnet-celoxof-weu3,0xb7614f7174a07028a5ff5e1adc68a031b646857f:mainnet-celoxof-weu4 -AZURE_ORACLE_WESTEUROPE_EURXOF_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0xd2c4f59724df51026f857a7e188b322e35256e24:mainnet-eurxof-weu0,0xe47c9867dbb37110834aaaf65b8d760c49c22081:mainnet-eurxof-weu1,0x9cb4896447a8f2611f5fb6f5fc853ffa16a1d864:mainnet-eurxof-weu2,0x0f9786b083c8c22e2e839286230098048a20a0ec:mainnet-eurxof-weu3,0xe01890c7760445908128f0e64e1170866566e1f6:mainnet-eurxof-weu4 -AZURE_ORACLE_WESTEUROPE_EUROCXOF_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0xdda1d71f3d5a6090bc04b77a18925fab7054d9c3:mainnet-eurocxof-weu0,0xee1d05f81e90b8ece440de6141282404e83830ce:mainnet-eurocxof-weu1,0xff6e35c6119742fd1eb3db780d976c4e55585108:mainnet-eurocxof-weu2,0x59eac333453279e71a3a98b4b72bdfa99ca51ad3:mainnet-eurocxof-weu3,0x378b95092bed2acb0d3ae6ab9c045eef1c250872:mainnet-eurocxof-weu4 -AZURE_ORACLE_WESTEUROPE_FULL_NODES_COUNT=5 -AZURE_ORACLE_WESTEUROPE_FULL_NODES_ROLLING_UPDATE_PARTITION=0 -AZURE_ORACLE_WESTEUROPE_FULL_NODES_DISK_SIZE=100 -AZURE_ORACLE_WESTEUROPE_FULL_NODES_RPC_API_METHODS="eth,net,rpc,web3" -AZURE_ORACLE_WESTEUROPE_FULL_NODES_GETH_GC_MODE="full" -AZURE_ORACLE_WESTEUROPE_FULL_NODES_USE_GSTORAGE_DATA=false -AZURE_ORACLE_WESTEUROPE_FULL_NODES_WS_PORT="8546" -AZURE_ORACLE_WESTEUROPE_PROM_SIDECAR_DISABLED="true" - -AZURE_ORACLE_EASTUS2_AZURE_SUBSCRIPTION_ID=7a6f5f20-bd43-4267-8c35-a734efca140c -AZURE_ORACLE_EASTUS2_AZURE_TENANT_ID=7cb7628a-e37c-4afb-8332-2029e418980e -AZURE_ORACLE_EASTUS2_AZURE_REGION_NAME=eus2 -AZURE_ORACLE_EASTUS2_AZURE_KUBERNETES_RESOURCE_GROUP=mainnet-oracles-eastus2 -AZURE_ORACLE_EASTUS2_KUBERNETES_CLUSTER_NAME=mainnet-oracles-eastus2 -# Format should be a comma-separated sequence of: -#
:: -# Set these when needed -AZURE_ORACLE_EASTUS2_CELOUSD_ORACLE_ADDRESS_AZURE_KEY_VAULTS= -AZURE_ORACLE_EASTUS2_FULL_NODES_COUNT=3 -AZURE_ORACLE_EASTUS2_FULL_NODES_ROLLING_UPDATE_PARTITION=0 -AZURE_ORACLE_EASTUS2_FULL_NODES_DISK_SIZE=100 -AZURE_ORACLE_EASTUS2_FULL_NODES_RPC_API_METHODS="eth,net,rpc,web3" -AZURE_ORACLE_EASTUS2_FULL_NODES_GETH_GC_MODE="full" -AZURE_ORACLE_EASTUS2_FULL_NODES_USE_GSTORAGE_DATA=false -AZURE_ORACLE_EASTUS2_FULL_NODES_WS_PORT="8546" -AZURE_ORACLE_EASTUS2_PROM_SIDECAR_DISABLED="true" - -# ---- Forno ---- - -# ---- General Forno ---- - -# A list of every context that forno will use. -FORNO_FULL_NODE_CONTEXTS=gcp-forno-us-west1,gcp-forno-us-east1,gcp-forno-asia-east1,gcp-forno-europe-west1,gcp-forno-southamerica-east1 -# A list of domains to provision the SSL certificate for -FORNO_DOMAINS=rc1-forno-k8s.celo-testnet.org.,forno.celo.org.,rc1-forno.celo-testnet.org. -# All forno clusters must be in this VPC -FORNO_VPC_NETWORK_NAME=rc1-network -# FORNO_BANNED_CIDR=139.162.18.181/32,99.76.58.161/32 -FORNO_BANNED_CIDR=99.76.58.161/32 - -# ---- Forno Contexts ---- - -GCP_FORNO_US_WEST1_GCP_PROJECT_NAME=celo-testnet-production -GCP_FORNO_US_WEST1_GCP_ZONE=us-west1-a -GCP_FORNO_US_WEST1_KUBERNETES_CLUSTER_NAME=rc1-us-west1 -GCP_FORNO_US_WEST1_FULL_NODES_COUNT=10 -GCP_FORNO_US_WEST1_FULL_NODES_ROLLING_UPDATE_PARTITION=0 -GCP_FORNO_US_WEST1_FULL_NODES_DISK_SIZE=150 -# NOTE: If these fullnodes are used for static nodes, changing this will result -# in the full nodes having a different nodekey -GCP_FORNO_US_WEST1_FULL_NODES_NODEKEY_DERIVATION_STRING=GCP_US_WEST1 -# suffix of the static nodes file, e.g. `.` -GCP_FORNO_US_WEST1_FULL_NODES_STATIC_NODES_FILE_SUFFIX=gcp-us-west1 -GCP_FORNO_US_WEST1_FULL_NODES_RPC_API_METHODS="eth,net,rpc,web3" -GCP_FORNO_US_WEST1_FULL_NODES_GETH_GC_MODE="full" -GCP_FORNO_US_WEST1_FULL_NODES_USE_GSTORAGE_DATA=true -GCP_FORNO_US_WEST1_FULL_NODES_WS_PORT="8546" - -GCP_FORNO_US_EAST1_GCP_PROJECT_NAME=celo-testnet-production -GCP_FORNO_US_EAST1_GCP_ZONE=us-east1-b -GCP_FORNO_US_EAST1_KUBERNETES_CLUSTER_NAME=rc1-us-east1 -GCP_FORNO_US_EAST1_FULL_NODES_COUNT=0 -GCP_FORNO_US_EAST1_FULL_NODES_ROLLING_UPDATE_PARTITION=0 -GCP_FORNO_US_EAST1_FULL_NODES_DISK_SIZE=150 -# NOTE: If these fullnodes are used for static nodes, changing this will result -# in the full nodes having a different nodekey -GCP_FORNO_US_EAST1_FULL_NODES_NODEKEY_DERIVATION_STRING=GCP_US_EAST1 -# suffix of the static nodes file, e.g. `.` -GCP_FORNO_US_EAST1_FULL_NODES_STATIC_NODES_FILE_SUFFIX=gcp-us-east1 -GCP_FORNO_US_EAST1_FULL_NODES_RPC_API_METHODS="eth,net,rpc,web3" -GCP_FORNO_US_EAST1_FULL_NODES_GETH_GC_MODE="full" -GCP_FORNO_US_EAST1_FULL_NODES_USE_GSTORAGE_DATA=true -GCP_FORNO_US_EAST1_FULL_NODES_WS_PORT="8546" - -GCP_FORNO_ASIA_EAST1_GCP_PROJECT_NAME=celo-testnet-production -GCP_FORNO_ASIA_EAST1_GCP_ZONE=asia-east1-a -GCP_FORNO_ASIA_EAST1_KUBERNETES_CLUSTER_NAME=rc1-asia-east1 -GCP_FORNO_ASIA_EAST1_FULL_NODES_COUNT=0 -GCP_FORNO_ASIA_EAST1_FULL_NODES_ROLLING_UPDATE_PARTITION=0 -GCP_FORNO_ASIA_EAST1_FULL_NODES_DISK_SIZE=150 -# NOTE: If these fullnodes are used for static nodes, changing this will result -# in the full nodes having a different nodekey -GCP_FORNO_ASIA_EAST1_FULL_NODES_NODEKEY_DERIVATION_STRING=GCP_ASIA_EAST1 -# suffix of the static nodes file, e.g. `.` -GCP_FORNO_ASIA_EAST1_FULL_NODES_STATIC_NODES_FILE_SUFFIX=gcp-asia-east1 -GCP_FORNO_ASIA_EAST1_FULL_NODES_RPC_API_METHODS="eth,net,rpc,web3" -GCP_FORNO_ASIA_EAST1_FULL_NODES_GETH_GC_MODE="full" -GCP_FORNO_ASIA_EAST1_FULL_NODES_USE_GSTORAGE_DATA=true -GCP_FORNO_ASIA_EAST1_FULL_NODES_WS_PORT="8546" - -GCP_FORNO_EUROPE_WEST1_GCP_PROJECT_NAME=celo-testnet-production -GCP_FORNO_EUROPE_WEST1_GCP_ZONE=europe-west1-b -GCP_FORNO_EUROPE_WEST1_KUBERNETES_CLUSTER_NAME=rc1-europe-west1 -GCP_FORNO_EUROPE_WEST1_FULL_NODES_COUNT=4 -GCP_FORNO_EUROPE_WEST1_FULL_NODES_ROLLING_UPDATE_PARTITION=0 -GCP_FORNO_EUROPE_WEST1_FULL_NODES_DISK_SIZE=150 -# NOTE: If these fullnodes are used for static nodes, changing this will result -# in the full nodes having a different nodekey -GCP_FORNO_EUROPE_WEST1_FULL_NODES_NODEKEY_DERIVATION_STRING=GCP_EUROPE_WEST1 -# suffix of the static nodes file, e.g. `.` -GCP_FORNO_EUROPE_WEST1_FULL_NODES_STATIC_NODES_FILE_SUFFIX=gcp-europe-west1 -GCP_FORNO_EUROPE_WEST1_FULL_NODES_RPC_API_METHODS="eth,net,rpc,web3" -GCP_FORNO_EUROPE_WEST1_FULL_NODES_GETH_GC_MODE="full" -GCP_FORNO_EUROPE_WEST1_FULL_NODES_USE_GSTORAGE_DATA=true -GCP_FORNO_EUROPE_WEST1_FULL_NODES_WS_PORT="8546" - -GCP_FORNO_SOUTHAMERICA_EAST1_GCP_PROJECT_NAME=celo-testnet-production -GCP_FORNO_SOUTHAMERICA_EAST1_GCP_ZONE=southamerica-east1-a -GCP_FORNO_SOUTHAMERICA_EAST1_KUBERNETES_CLUSTER_NAME=rc1-southamerica-east1 -GCP_FORNO_SOUTHAMERICA_EAST1_FULL_NODES_COUNT=0 -GCP_FORNO_SOUTHAMERICA_EAST1_FULL_NODES_ROLLING_UPDATE_PARTITION=0 -GCP_FORNO_SOUTHAMERICA_EAST1_FULL_NODES_DISK_SIZE=150 -# NOTE: If these fullnodes are used for static nodes, changing this will result -# in the full nodes having a different nodekey -GCP_FORNO_SOUTHAMERICA_EAST1_FULL_NODES_NODEKEY_DERIVATION_STRING=GCP_SOUTHAMERICA_EAST1 -# suffix of the static nodes file, e.g. `.` -GCP_FORNO_SOUTHAMERICA_EAST1_FULL_NODES_STATIC_NODES_FILE_SUFFIX=gcp-southamerica-east1 -GCP_FORNO_SOUTHAMERICA_EAST1_FULL_NODES_RPC_API_METHODS="eth,net,rpc,web3" -GCP_FORNO_SOUTHAMERICA_EAST1_FULL_NODES_GETH_GC_MODE="full" -GCP_FORNO_SOUTHAMERICA_EAST1_FULL_NODES_USE_GSTORAGE_DATA=true -GCP_FORNO_SOUTHAMERICA_EAST1_FULL_NODES_WS_PORT="8546" - -# ---- Private txnodes context ---- - -# CPU and memory requests can be customized in packages/helm-charts/celo-fullnode/rc1-gcp-private-txnodes-values.yaml -GCP_PRIVATE_TXNODES_GCP_PROJECT_NAME=celo-testnet-production -GCP_PRIVATE_TXNODES_GCP_ZONE=us-west1-a -GCP_PRIVATE_TXNODES_KUBERNETES_CLUSTER_NAME=mainnet -GCP_PRIVATE_TXNODES_FULL_NODES_COUNT=8 -GCP_PRIVATE_TXNODES_FULL_NODES_ROLLING_UPDATE_PARTITION=0 -GCP_PRIVATE_TXNODES_FULL_NODES_DISK_SIZE=300 -GCP_PRIVATE_TXNODES_FULL_NODES_RPC_API_METHODS="eth,net,rpc,web3,txpool,debug" -GCP_PRIVATE_TXNODES_FULL_NODES_GETH_GC_MODE="archive" -GCP_PRIVATE_TXNODES_FULL_NODES_USE_GSTORAGE_DATA=false -GCP_PRIVATE_TXNODES_FULL_NODES_WS_PORT="8545" - -TRANSACTION_METRICS_EXPORTER_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/celo-monorepo" -TRANSACTION_METRICS_EXPORTER_DOCKER_IMAGE_TAG="transaction-metrics-exporter-f4a55e143932ea559cf4bcbd9bcccc14da43d6ed" - -# Genesis Vars -NETWORK_ID=42220 -CONSENSUS_TYPE="istanbul" -BLOCK_TIME=5 -EPOCH=17280 -LOOKBACK=12 -ISTANBUL_REQUEST_TIMEOUT_MS=3000 - -# the number of load test clients that will be given funds in the genesis & migrations -LOAD_TEST_CLIENTS=0 -# every 7.2 seconds, so that 500 transactions are sent by a client every hour -# to simulate 10,000 total transactions per hour -LOAD_TEST_TX_DELAY_MS=7200 - -# the amount in cUSD wei to give faucet, load test, and attestation bot accounts -FAUCET_CUSD_WEI=0 - -# Baklava is run entirely by non-cLabs validators -VALIDATORS=0 -PROXIED_VALIDATORS=0 -ELECTION_MIN_VALIDATORS=22 -TX_NODES=10 -# Nodes whose RPC ports are only internally exposed -PRIVATE_TX_NODES=4 - -# STATIC_IPS_FOR_GETH_NODES=false -# Whether tx_nodes/validators stateful set should use ssd persistent disks -# GETH_NODES_SSD_DISKS=true -IN_MEMORY_DISCOVERY_TABLE=false -# PING_IP_FROM_PACKET=false - -CLUSTER_CREATION_FLAGS="--enable-autoscaling --min-nodes 3 --max-nodes 8 --machine-type=n1-standard-4" - -GETH_NODE_CPU_REQUEST=400m -GETH_NODE_MEMORY_REQUEST=2.5G -# Used for validators, proxies, and tx_nodes -NODE_DISK_SIZE_GB=100 -# Used for private tx_nodes (gcmode archive) -PRIVATE_NODE_DISK_SIZE_GB=200 - -VERIFICATION_POOL_URL="https://us-central1-celo-testnet.cloudfunctions.net/handleVerificationRequestbaklava/v0.1/sms/" -VERIFICATION_REWARDS_URL="https://us-central1-celo-testnet.cloudfunctions.net/handleVerificationRequestbaklava/v0.1/rewards/" - -# Disable the sidecar that forwards the metrics to stackdriver -PROMETHEUS_DISABLE_STACKDRIVER_SIDECAR="true" - -MOBILE_WALLET_PLAYSTORE_LINK="https://play.google.com/apps/internaltest/4700990475000634666" - -# Number of gold-holding bots that vote for validator groups -VOTING_BOTS=0 -# 10,000 CG -VOTING_BOT_BALANCE=10000000000000000000000 - -# Probability that a given bot account will participate in the current epoch's voting -VOTING_BOT_WAKE_PROBABILITY=0 - -# Baseline probability of changing vote once woken. If the group that this bot account -# has currently voted for is 1, this is the probability the bot will change their vote -VOTING_BOT_CHANGE_BASELINE=0 - -# The probability that when choosing a new group to vote for, it will choose a never-elected group -# Should be in the range of 0 to 1. Lower values bias towards incumbency. Higher values bias -# towards novelty. -VOTING_BOT_EXPLORE_PROBABILITY=0.6 - -# This value is used to determine how heavily a group's score weigh in the bot's voting decision -# Should be a positive number. 1 is a linear relationship. Higher values increase the separation -# among high scores. Less than 1 has a steep drop-off for low-scoring groups. -VOTING_BOT_SCORE_SENSITIVITY=1 - -# Schedule for the voting bot process, deployed via celotool, expressed in crontab syntax -# Minimum epoch length is 1 hour. This cron schedule is "every hour at minute 1", in order -# to run once an epoch. -# Notes: -# - if an epoch takes longer, this will occasionally run twice in an epoch -# - Running on minute 1 is arbitrary. This could be any value from 0-59. -VOTING_BOT_CRON_SCHEDULE="1 * * * *" - -# --- ODIS --- - -# ODIS azure k8s deployments -ODIS_SIGNER_DOCKER_IMAGE_REPOSITORY=us.gcr.io/celo-testnet/celo-monorepo -ODIS_SIGNER_DOCKER_IMAGE_TAG=oblivious-decentralized-identifier-service-1.1.10 -ODIS_SIGNER_BLOCKCHAIN_PROVIDER="https://forno.celo.org" -# Options: json, human (default), stackdriver -LOG_FORMAT=stackdriver -# Options: fatal, error, warn, info (default), debug, trace -LOG_LEVEL=info - - -# ODIS signer WESTUS2 A Azure info -AZURE_ODIS_WESTUS2_A_AZURE_SUBSCRIPTION_ID=7a6f5f20-bd43-4267-8c35-a734efca140c -AZURE_ODIS_WESTUS2_A_AZURE_TENANT_ID=7cb7628a-e37c-4afb-8332-2029e418980e -AZURE_ODIS_WESTUS2_A_AZURE_REGION_NAME=weus2 - -# ODIS signer WESTUS2 A K8S cluster info -AZURE_ODIS_WESTUS2_A_AZURE_KUBERNETES_RESOURCE_GROUP=mainnet-pgpnp-westus2 -AZURE_ODIS_WESTUS2_A_KUBERNETES_CLUSTER_NAME=odis-mainnet-westus2-a-v2 - -# ODIS signer WESTUS2 A Postgres DB -AZURE_ODIS_WESTUS2_A_ODIS_SIGNER_DB_HOST=mainnet-pgpnp-db-westus2.postgres.database.azure.com -AZURE_ODIS_WESTUS2_A_ODIS_SIGNER_DB_PORT=5432 -AZURE_ODIS_WESTUS2_A_ODIS_SIGNER_DB_USERNAME=clabs@mainnet-pgpnp-db-westus2 - -# ODIS signer WESTUS2 A Key Vault -AZURE_ODIS_WESTUS2_A_ODIS_SIGNER_AZURE_KEYVAULT_NAME=mainnet-pgpnp-westus2 -AZURE_ODIS_WESTUS2_A_ODIS_SIGNER_AZURE_KEYVAULT_PNP_KEY_NAME_BASE=phoneNumberPrivacy -AZURE_ODIS_WESTUS2_A_ODIS_SIGNER_AZURE_KEYVAULT_PNP_KEY_LATEST_VERSION=1 -AZURE_ODIS_WESTUS2_A_ODIS_SIGNER_AZURE_KEYVAULT_DOMAINS_KEY_NAME_BASE=domains -AZURE_ODIS_WESTUS2_A_ODIS_SIGNER_AZURE_KEYVAULT_DOMAINS_KEY_LATEST_VERSION=1 - -# ODIS signer WESTUS2 A Network -AZURE_ODIS_WESTUS2_A_ODIS_NETWORK=mainnet - -# ODIS signer WESTUS2 A Prometheus config -AZURE_ODIS_WESTUS2_A_PROM_SCRAPE_JOB_NAME=scrape-odis -AZURE_ODIS_WESTUS2_A_PROM_SCRAPE_LABELS="_generic_location: us-west2,_generic_namespace: odis-signer" -AZURE_ODIS_WESTUS2_A_PROM_SCRAPE_TARGETS="odis-mainnet-westus2-a-v2.rc1:3000" -AZURE_ODIS_WESTUS2_A_PROM_SIDECAR_GCP_PROJECT=celo-pgpnp-mainnet -AZURE_ODIS_WESTUS2_A_PROM_SIDECAR_GCP_REGION=us-west2 -AZURE_ODIS_WESTUS2_A_PROM_SIDECAR_DISABLED="true" - - -# ODIS signer WESTEUROPE A Azure info -AZURE_ODIS_WESTEUROPE_A_AZURE_SUBSCRIPTION_ID=7a6f5f20-bd43-4267-8c35-a734efca140c -AZURE_ODIS_WESTEUROPE_A_AZURE_TENANT_ID=7cb7628a-e37c-4afb-8332-2029e418980e -AZURE_ODIS_WESTEUROPE_A_AZURE_REGION_NAME=weeu - -# ODIS signer WESTEUROPE A K8S cluster info -AZURE_ODIS_WESTEUROPE_A_AZURE_KUBERNETES_RESOURCE_GROUP=mainnet-pgpnp-westeurope -AZURE_ODIS_WESTEUROPE_A_KUBERNETES_CLUSTER_NAME=odis-mainnet-westeurope-a-v2 - -# ODIS signer WESTEUROPE A Postgres DB -AZURE_ODIS_WESTEUROPE_A_ODIS_SIGNER_DB_HOST=mainnet-pgpnp-westeurope.postgres.database.azure.com -AZURE_ODIS_WESTEUROPE_A_ODIS_SIGNER_DB_PORT=5432 -AZURE_ODIS_WESTEUROPE_A_ODIS_SIGNER_DB_USERNAME=cLabs@mainnet-pgpnp-westeurope - -# ODIS signer WESTEUROPE A Key Vault -AZURE_ODIS_WESTEUROPE_A_ODIS_SIGNER_AZURE_KEYVAULT_NAME=mainnet-pgpnp-westeurope -AZURE_ODIS_WESTEUROPE_A_ODIS_SIGNER_AZURE_KEYVAULT_PNP_KEY_NAME_BASE=phoneNumberPrivacy -AZURE_ODIS_WESTEUROPE_A_ODIS_SIGNER_AZURE_KEYVAULT_PNP_KEY_LATEST_VERSION=1 -AZURE_ODIS_WESTEUROPE_A_ODIS_SIGNER_AZURE_KEYVAULT_DOMAINS_KEY_NAME_BASE=domains -AZURE_ODIS_WESTEUROPE_A_ODIS_SIGNER_AZURE_KEYVAULT_DOMAINS_KEY_LATEST_VERSION=1 - -# ODIS signer WESTEUROPE A Network -AZURE_ODIS_WESTEUROPE_A_ODIS_NETWORK=mainnet - -# ODIS signer WESTEUROPE A Prometheus config -AZURE_ODIS_WESTEUROPE_A_PROM_SCRAPE_JOB_NAME=scrape-odis -AZURE_ODIS_WESTEUROPE_A_PROM_SCRAPE_LABELS="_generic_location: europe-west2-a,_generic_namespace: odis-signer" -AZURE_ODIS_WESTEUROPE_A_PROM_SCRAPE_TARGETS="odis-mainnet-westeurope-a-v2.rc1:3000" -AZURE_ODIS_WESTEUROPE_A_PROM_SIDECAR_GCP_PROJECT=celo-pgpnp-mainnet -AZURE_ODIS_WESTEUROPE_A_PROM_SIDECAR_GCP_REGION=europe-west2-a -AZURE_ODIS_WESTEUROPE_A_PROM_SIDECAR_DISABLED="true" - - -# ODIS signer EASTASIA A Azure info -AZURE_ODIS_EASTASIA_A_AZURE_SUBSCRIPTION_ID=7a6f5f20-bd43-4267-8c35-a734efca140c -AZURE_ODIS_EASTASIA_A_AZURE_TENANT_ID=7cb7628a-e37c-4afb-8332-2029e418980e -AZURE_ODIS_EASTASIA_A_AZURE_REGION_NAME=eaas - -# ODIS signer EASTASIA A K8S cluster info -AZURE_ODIS_EASTASIA_A_AZURE_KUBERNETES_RESOURCE_GROUP=mainnet-pgpnp-eastasia -AZURE_ODIS_EASTASIA_A_KUBERNETES_CLUSTER_NAME=odis-mainnet-eastasia-a-v2 - -# ODIS signer EASTASIA A Postgres DB -AZURE_ODIS_EASTASIA_A_ODIS_SIGNER_DB_HOST=mainnet-pgpnp-db-eastasia.postgres.database.azure.com -AZURE_ODIS_EASTASIA_A_ODIS_SIGNER_DB_PORT=5432 -AZURE_ODIS_EASTASIA_A_ODIS_SIGNER_DB_USERNAME=clabs@mainnet-pgpnp-db-eastasia - -# ODIS signer EASTASIA A Key Vault -AZURE_ODIS_EASTASIA_A_ODIS_SIGNER_AZURE_KEYVAULT_NAME=mainnet-pgpnp-eastasia -AZURE_ODIS_EASTASIA_A_ODIS_SIGNER_AZURE_KEYVAULT_PNP_KEY_NAME_BASE=phoneNumberPrivacy -AZURE_ODIS_EASTASIA_A_ODIS_SIGNER_AZURE_KEYVAULT_PNP_KEY_LATEST_VERSION=1 -AZURE_ODIS_EASTASIA_A_ODIS_SIGNER_AZURE_KEYVAULT_DOMAINS_KEY_NAME_BASE=domains -AZURE_ODIS_EASTASIA_A_ODIS_SIGNER_AZURE_KEYVAULT_DOMAINS_KEY_LATEST_VERSION=1 - -# ODIS signer EASTASIA A Network -AZURE_ODIS_EASTASIA_A_ODIS_NETWORK=mainnet - -# ODIS signer EASTASIA A Prometheus config -AZURE_ODIS_EASTASIA_A_PROM_SCRAPE_JOB_NAME=scrape-odis -AZURE_ODIS_EASTASIA_A_PROM_SCRAPE_LABELS="_generic_location: asia-east1-a,_generic_namespace: odis-signer" -AZURE_ODIS_EASTASIA_A_PROM_SCRAPE_TARGETS="odis-mainnet-eastasia-a-v2.rc1:3000" -AZURE_ODIS_EASTASIA_A_PROM_SIDECAR_GCP_PROJECT=celo-pgpnp-mainnet -AZURE_ODIS_EASTASIA_A_PROM_SIDECAR_GCP_REGION=asia-east1-a -AZURE_ODIS_EASTASIA_A_PROM_SIDECAR_DISABLED="true" - - -# ODIS signer BRAZILSOUTH A Azure info -AZURE_ODIS_BRAZILSOUTH_A_AZURE_SUBSCRIPTION_ID=7a6f5f20-bd43-4267-8c35-a734efca140c -AZURE_ODIS_BRAZILSOUTH_A_AZURE_TENANT_ID=7cb7628a-e37c-4afb-8332-2029e418980e -AZURE_ODIS_BRAZILSOUTH_A_AZURE_REGION_NAME=brso - -# ODIS signer BRAZILSOUTH A K8S cluster info -AZURE_ODIS_BRAZILSOUTH_A_AZURE_KUBERNETES_RESOURCE_GROUP=mainnet-pgpnp-brazilsouth -AZURE_ODIS_BRAZILSOUTH_A_KUBERNETES_CLUSTER_NAME=odis-mainnet-brazilsouth-a-v2 - -# ODIS signer BRAZILSOUTH A Postgres DB -AZURE_ODIS_BRAZILSOUTH_A_ODIS_SIGNER_DB_HOST=mainnet-pgpnp-db-brazilsouth.postgres.database.azure.com -AZURE_ODIS_BRAZILSOUTH_A_ODIS_SIGNER_DB_PORT=5432 -AZURE_ODIS_BRAZILSOUTH_A_ODIS_SIGNER_DB_USERNAME=clabs@mainnet-pgpnp-db-brazilsouth - -# ODIS signer BRAZILSOUTH A Key Vault -AZURE_ODIS_BRAZILSOUTH_A_ODIS_SIGNER_AZURE_KEYVAULT_NAME=mainnet-pgpnp-brazil -AZURE_ODIS_BRAZILSOUTH_A_ODIS_SIGNER_AZURE_KEYVAULT_PNP_KEY_NAME_BASE=phoneNumberPrivacy -AZURE_ODIS_BRAZILSOUTH_A_ODIS_SIGNER_AZURE_KEYVAULT_PNP_KEY_LATEST_VERSION=1 -AZURE_ODIS_BRAZILSOUTH_A_ODIS_SIGNER_AZURE_KEYVAULT_DOMAINS_KEY_NAME_BASE=domains -AZURE_ODIS_BRAZILSOUTH_A_ODIS_SIGNER_AZURE_KEYVAULT_DOMAINS_KEY_LATEST_VERSION=1 - -# ODIS signer BRAZILSOUTH A Network -AZURE_ODIS_BRAZILSOUTH_A_ODIS_NETWORK=mainnet - -# ODIS signer BRAZILSOUTH A Prometheus config -AZURE_ODIS_BRAZILSOUTH_A_PROM_SCRAPE_JOB_NAME=scrape-odis -AZURE_ODIS_BRAZILSOUTH_A_PROM_SCRAPE_LABELS="_generic_location: southamerica-east1-a,_generic_namespace: odis-signer" -AZURE_ODIS_BRAZILSOUTH_A_PROM_SCRAPE_TARGETS="odis-mainnet-brazilsouth-a-v2.rc1:3000" -AZURE_ODIS_BRAZILSOUTH_A_PROM_SIDECAR_GCP_PROJECT=celo-pgpnp-mainnet -AZURE_ODIS_BRAZILSOUTH_A_PROM_SIDECAR_GCP_REGION=southamerica-east1-a -AZURE_ODIS_BRAZILSOUTH_A_PROM_SIDECAR_DISABLED="true" - -# For WalletConnect relay -WALLET_CONNECT_IMAGE_REPOSITORY='us.gcr.io/celo-testnet/walletconnect' -WALLET_CONNECT_IMAGE_TAG='1472bcaad57e3746498f7a661c42ff5cf9acaf5a' -WALLET_CONNECT_REDIS_CLUSTER_ENABLED=false -WALLET_CONNECT_REDIS_CLUSTER_USEPASSWORD=false \ No newline at end of file diff --git a/.env.rc1staging b/.env.rc1staging deleted file mode 100644 index 8d651268d..000000000 --- a/.env.rc1staging +++ /dev/null @@ -1,23 +0,0 @@ -# Don't use "//" for comments in this file. -# This file is meant to be executed as a bash script for testing. -ENV_TYPE="staging" - -GETH_VERBOSITY=2 -GETH_ENABLE_METRICS=true - -KUBERNETES_CLUSTER_NAME="rc1staging" -KUBERNETES_CLUSTER_ZONE="us-west1-a" -CLUSTER_DOMAIN_NAME="celo-testnet" - -TESTNET_PROJECT_NAME="celo-testnet-production" - -BLOCKSCOUT_DOCKER_IMAGE_TAG="0362f9f4d1d4842f27adb634d628f969f53c046d" -BLOCKSCOUT_DB_SUFFIX="" - -# The archive nodes are managed throught the Helm charts. - -NETWORK_ID=42220 -PRIVATE_TX_NODES=2 - -# Disable the sidecar that forwards the metrics to stackdriver -PROMETHEUS_DISABLE_STACKDRIVER_SIDECAR="true" \ No newline at end of file diff --git a/.env.staging b/.env.staging deleted file mode 100644 index 4dc0ef883..000000000 --- a/.env.staging +++ /dev/null @@ -1,55 +0,0 @@ - -ORACLE_DOCKER_IMAGE_REPOSITORY="celotestnet.azurecr.io/testnet/oracle" -ORACLE_DOCKER_IMAGE_TAG="fdeb1f24de899d494337cf14bee9c7d09ba7b54e" - -ORACLE_UNUSED_ORACLE_ADDRESSES= - -# each context should have its own environment variables, generally of the form -# _* -CONTEXTS=azure-eastus - -AZURE_EASTUS_AZURE_SUBSCRIPTION_ID=97e2b592-255b-4f92-bce0-127257163c36 -AZURE_EASTUS_AZURE_TENANT_ID=7cb7628a-e37c-4afb-8332-2029e418980e -AZURE_EASTUS_AZURE_KUBERNETES_RESOURCE_GROUP=testnet-oracle-eastus -AZURE_EASTUS_KUBERNETES_CLUSTER_NAME=testnet-oracle-eastus -AZURE_EASTUS_AZURE_REGION_NAME=eastus - -# Format should be a comma-separated sequence of: -#
:: -AZURE_EASTUS_CELOUSD_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x21860ca3a0a6f7e450b8f24bd00eac7ba766b85e:testnet-oracle-eastus,0xfd3738e5e0a020614a9e5253078dda491e77031c:testnet-oracle-eastus -AZURE_EASTUS_CELOEUR_ORACLE_ADDRESS_AZURE_KEY_VAULTS=0x4D169C0Ec17D3dEcB250701Aa64e966bE98a696B:testnet-oracle-eastus,0x034217fB0C08dec29a6beA99e75aAC39baf7459A:testnet-oracle-eastus,0xD20f803a1489849031725479Df27741c3326eD15:testnet-oracle-eastus,0x26412103865Be3F80152EA10E61E6294ed0e0DC9:testnet-oracle-eastus,0x7Ba21D1f769Ae9feCF58dEfB5bD08905Bd3B707B:testnet-oracle-eastus -# AZURE_EASTUS_CELOUSD_ORACLE_ADDRESSES_FROM_MNEMONIC_COUNT= -AZURE_EASTUS_FULL_NODES_COUNT=2 -AZURE_EASTUS_FULL_NODES_DISK_SIZE=10 - -# ---- General ---- - -ENV_TYPE="development" -CLUSTER_DOMAIN_NAME="celo-networks-dev" -TESTNET_PROJECT_NAME="celo-testnet" - -# ---- Geth ---- - -GETH_NODE_DOCKER_IMAGE_REPOSITORY="us.gcr.io/celo-testnet/geth" -# When upgrading change this to latest commit hash from the master of the geth repo -# `geth $ git show | head -n 1` -GETH_NODE_DOCKER_IMAGE_TAG="8a44c2cd92200bdffce595c7558e84a39ea2bc15" - -GETH_VERBOSITY=2 - - -KUBERNETES_CLUSTER_NAME=celo-networks-dev -KUBERNETES_CLUSTER_ZONE="us-west1-a" - -GETH_BOOTNODE_DOCKER_IMAGE_REPOSITORY="us.gcr.io/celo-testnet/geth-all" -# When upgrading change this to latest commit hash from the master of the geth repo -# `geth $ git show | head -n 1` -GETH_BOOTNODE_DOCKER_IMAGE_TAG="8a44c2cd92200bdffce595c7558e84a39ea2bc15" - -# ---- Genesis Vars ---- - -NETWORK_ID=1101 -CONSENSUS_TYPE="istanbul" -PREDEPLOYED_CONTRACTS="REGISTRY" -BLOCK_TIME=5 -EPOCH=720 \ No newline at end of file diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c9b7671cf..e60fde298 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -10,19 +10,8 @@ .github/actions/ @celo-org/devopsre .github/workflows/ @celo-org/devopsre -/dockerfiles/ @celo-org/devopsre -/packages/celotool/ @celo-org/devopsre /packages/cli/ @celo-org/devtooling -/packages/dev-utils/ @celo-org/devtooling /packages/docs/ @celo-org/devtooling @celo-org/primitives @celo-org/devrel -/packages/env-tests/ @celo-org/primitives -/packages/faucet/ @celo-org/devtooling -/packages/helm-charts/ @celo-org/devopsre -/packages/helm-charts/mock-oracle/ @celo-org/mento @celo-org/devopsre -/packages/helm-charts/oracle-rbac/ @celo-org/mento @celo-org/devopsre -/packages/helm-charts/oracle/ @celo-org/mento @celo-org/devopsre /packages/metadata-crawler/ @celo-org/devopsre -/packages/protocol/ @celo-org/primitives /packages/sdk/ @celo-org/devtooling -/packages/typescript/ @celo-org/devtooling diff --git a/.github/ISSUE_TEMPLATE/gitcoin-bounty-issue.md b/.github/ISSUE_TEMPLATE/gitcoin-bounty-issue.md deleted file mode 100644 index f410bfd74..000000000 --- a/.github/ISSUE_TEMPLATE/gitcoin-bounty-issue.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -name: New Gitcoin Bounty Issue -about: Use this template to propose new Gitcoin bounties. -title: "[BOUNTY]: " -labels: dog -assignees: reachjason,critesjosh,barbaraliau,aslawson ---- - -### Issue Title - -### Challenge Description - -Be as descriptive as possible about what you want to see built. Challenges should be useful to Celo, but open-ended enough to allow for creativity from hackers. - -### Submission Requirements - -What constitutes a valid/good submission to win the bounty? Would you like a demo included in the submission (Strongly Recommended)? What will help you determine whether a submission passed a threshold of acceptable quality? Please include any relevant code contribution guidelines/standards, etc. Is there any criteria? - -How will we ultimately decide the winner/winners from all valid submissions? Typically clean successful PR merge? First valid submission received? Best submission meeting some criteria by the deadline? - -We review the submissions as early as possible (sometimes immediately upon submission) to ensure prompt winner announcement and payout. - -### Prerequisites - -What prerequisite knowledge does this bounty require? What specific topics does someone need to know about before they can start work? Is there setup required before they can begin work? If so, what do they need to do? - -### Time Expectation - -Given someone has the expected prerequisites and knowledge, what is the expected time investment? - -### Category - -_Front End, Back end, Design, Documentation or Other_ - -### Project Type - -- *Traditional - One contributor, one person paid* -- *Contest - Multiple people can contribute, one person is paid* -- *Cooperative - multiple people can contribute, multiple people are paid* - -### Permissions - -- *Approval Required: Bounty hunters should be approved before starting work* -- *Permissionless: No approval required* - -### Experience Lever - -Beginner, Intermediate or Advanced - -### Bounty Type - -Bug, Feature, Improvement, Security, Documentation, Design, Code Review, Other - -### Expiration - -When does this bounty expire? (if applicable) - -### Resources - -Link any relevant resources (e.g. specific documentation, source code that may be useful) - diff --git a/.github/ISSUE_TEMPLATE/issue-template.md b/.github/ISSUE_TEMPLATE/issue-template.md index 14e9a0e65..3c2f6ed5b 100644 --- a/.github/ISSUE_TEMPLATE/issue-template.md +++ b/.github/ISSUE_TEMPLATE/issue-template.md @@ -1,9 +1,9 @@ --- name: Add a New Issue -about: Use this template raise an issue in the Celo Monorepo. +about: Use this template raise an issue in the Celo Developer Tooling Repo. title: "[Issue Title]" -labels: -assignees: +labels: +assignees: @celo-org/devtooling --- diff --git a/.github/workflows/celo-monorepo.yml b/.github/workflows/celo-monorepo.yml deleted file mode 100644 index cfd3d176d..000000000 --- a/.github/workflows/celo-monorepo.yml +++ /dev/null @@ -1,608 +0,0 @@ -name: Build & Integration Tests -run-name: 'Build & Integration Tests: ${{ github.head_ref || github.ref_name }}' - -# Dockefile for the self-hosted runner: -# https://github.com/celo-org/infrastructure/blob/master/terraform/root-modules/gcp/integration-tests-gke/files/github-arc/Dockerfile-monorepo - -on: - push: - branches: - - master - - changeset-release/master - pull_request: - branches: - - master - - 'release/**' - - 'prerelease/**' - -concurrency: - group: celo-monorepo-${{ github.ref }} - cancel-in-progress: true - -defaults: - run: - shell: bash --login -eo pipefail {0} - -env: - # Increment these to force cache rebuilding - NODE_MODULE_CACHE_VERSION: 4 - NODE_OPTIONS: '--max-old-space-size=4096' - TERM: dumb - GRADLE_OPTS: '-Dorg.gradle.daemon=false -Dorg.gradle.parallel=false -Dorg.gradle.configureondemand=true -Dorg.gradle.jvmargs="-Xmx4096m -XX:+HeapDumpOnOutOfMemoryError"' - # Git Tag for contract release to use - #RELEASE_TAG: ganache-v7-core-contracts.v9 - RELEASE_TAG: core-contracts.v10 - # CELO_BLOCKCHAIN_BRANCH_TO_TEST: master - CELO_BLOCKCHAIN_BRANCH_TO_TEST: release/1.7.x - -# EXAMPLE on debug ssh step -# - name: Setup tmate session -# uses: mxschmitt/action-tmate@v3 -# timeout-minutes: 20 -# if: contains(matrix.command, 'common/') && false -# with: -# limit-access-to-actor: true - -jobs: - install-dependencies: - name: Install dependencies - outputs: - # Propagate more outputs if you need https://github.com/tj-actions/changed-files#outputs - # Adding a initial comma so ',' matches also for the first file - all_modified_files: ',${{ steps.changed-files.outputs.all_modified_files }}' - artifacts_to_cache: ${{ steps.get_artifacts_to_cache.outputs.artifacts_to_cache }} - # runs-on: ubuntu-latest - runs-on: ['self-hosted', 'monorepo-node18'] - timeout-minutes: 30 - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Restore node cache - uses: actions/cache@v3 - id: cache_node - with: - # We need to cache all the artifacts generated by yarn install+build - # Update this list also in .github/actions/sync-workspace/action.yml with exactly the same list - path: | - node_modules - packages/**/node_modules - key: node-${{ runner.os }}-${{ runner.arch }}-${{ env.NODE_MODULE_CACHE_VERSION }}-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - node-${{ runner.os }}-${{ runner.arch }}-${{ env.NODE_MODULE_CACHE_VERSION }}- - - name: Install yarn dependencies - run: git config --global url."https://".insteadOf ssh:// && yarn install - if: steps.cache_node.outputs.cache-hit != 'true' - - name: Run yarn postinstall if cache hitted - run: yarn run postinstall - if: steps.cache_node.outputs.cache-hit == 'true' - - name: Build packages - run: yarn build --ignore docs --include-dependencies - - name: Check licenses - if: steps.cache_node.outputs.cache-hit != 'true' - run: | - yarn check-licenses - # Get a list of submodules to ignore in the changed files check - - name: Get submodules to ignore in changed files check - id: get_submodules_to_ignore - run: | - # Get all the submodules paths - submodules=$(git config --file .gitmodules --name-only --get-regexp path) - # Remove the "submodule." prefix and ".path" suffix - submodules=$(echo $submodules | sed 's/^submodule.//g') - submodules=$(echo $submodules | sed 's/.path$//g') - # Add a ! in front of each path to ignore it latter in the changed files check - submodules=$(echo $submodules | sed 's/^/!/g') - echo "submodules<> $GITHUB_OUTPUT - echo "$submodules" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - # Get workdir local changes and fail if there are any change - - name: Verify Changed files - id: verify-changed-files - uses: tj-actions/verify-changed-files@v16 - with: - fail-if-changed: 'true' - fail-message: 'Files changed during build. Please build locally and commit the changes.' - files: | - **/* - ${{ steps.get_submodules_to_ignore.outputs.submodules }} - - run: | - echo "${{ steps.verify-changed-files.outputs.changed_files }}" - - name: Get the artifacts to cache - id: get_artifacts_to_cache - run: | - artifacts_to_cache="$(git ls-files --others --ignored --exclude-standard | grep -v node_modules | grep -v .js.map)" - echo "artifacts_to_cache<> $GITHUB_OUTPUT - echo "$artifacts_to_cache" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - # We use cache to share the build artifacts between jobs (gh artifacts are too slow...) - # For more context check https://github.com/actions/upload-artifact/issues/199 - - name: Restore build artifacts cache - uses: actions/cache@v3 - id: cache_build_artifacts - with: - # We need to cache all the artifacts generated by yarn install+build - # Update this list also in .github/actions/sync-workspace/action.yml with exactly the same list - path: | - ${{ steps.get_artifacts_to_cache.outputs.artifacts_to_cache }} - key: code-${{ github.sha }} - restore-keys: | - code-${{ github.sha }} - - name: Detect files changed in PR (or commit), and expose as output - id: changed-files - uses: tj-actions/changed-files@v37 - with: - # Using comma as separator to be able to easily match full paths (using ,) - separator: ',' - # Checking if changed in the last 100 commits in PRs - fetch_depth: '150' - - run: echo ",${{ steps.changed-files.outputs.all_modified_files }}" - - lint-checks: - name: Lint code - runs-on: ['self-hosted', 'monorepo-node18'] - timeout-minutes: 30 - needs: install-dependencies - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Sync workspace - uses: ./.github/actions/sync-workspace - with: - artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }} - - run: yarn run prettify:diff - - run: yarn run lint - general_test: - name: General jest test - runs-on: ['self-hosted', 'monorepo-node18'] - needs: install-dependencies - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Sync workspace - uses: ./.github/actions/sync-workspace - with: - artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }} - - name: Run Jest Tests - run: | - mkdir -p test-results/jest - # Skipping packages that are tested in a specific job below - yarn run lerna \ - --ignore @celo/contractkit \ - --ignore @celo/protocol \ - --ignore @celo/celotool \ - --ignore @celo/celocli \ - --ignore @celo/env-tests \ - --ignore '@celo/wallet-*' \ - run test - - name: Upload Jest Test Results - uses: actions/upload-artifact@v3 - with: - name: Jest Test Results - path: test-results/jest - wallet-test: - name: Wallet test - runs-on: ['self-hosted', 'monorepo-node18'] - timeout-minutes: 30 - needs: install-dependencies - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Sync workspace - uses: ./.github/actions/sync-workspace - with: - artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }} - - name: Run Wallet tests - run: | - yarn run lerna --scope '@celo/wallet-*' run test - - protocol-test-release: - name: Protocol Test Release - runs-on: ['self-hosted', 'monorepo-node18'] - timeout-minutes: 500 - needs: [install-dependencies, lint-checks] - if: | - github.base_ref == 'master' || contains(github.base_ref, 'staging') || contains(github.base_ref, 'production') || - contains(needs.install-dependencies.outputs.all_modified_files, 'packages/protocol') || - contains(needs.install-dependencies.outputs.all_modified_files, 'packages/sdk') || - contains(needs.install-dependencies.outputs.all_modified_files, 'packages/typescript') || - contains(needs.install-dependencies.outputs.all_modified_files, ',package.json') || - contains(needs.install-dependencies.outputs.all_modified_files, ',yarn.lock') || - false - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - submodules: recursive - - name: Sync workspace - uses: ./.github/actions/sync-workspace - with: - artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }} - - name: Download protocol devchain artifact - uses: dawidd6/action-download-artifact@v2 - with: - workflow: protocol-devchain.yml - name: devchain-${{ env.RELEASE_TAG }} - path: packages/protocol/.tmp/devchain - - name: Copy DevChain and Build generated from released tag - run: | - BUILD_AND_DEVCHAIN_DIR=$(echo build/$(echo $RELEASE_TAG | sed -e 's/\//_/g')) - (cp -r packages/protocol/.tmp/devchain packages/protocol/$BUILD_AND_DEVCHAIN_DIR) - - name: Test against current release - run: | - echo "Comparing against $RELEASE_TAG" - BUILD_AND_DEVCHAIN_DIR=$(echo build/$(echo $RELEASE_TAG | sed -e 's/\//_/g')) - yarn --cwd packages/protocol ci:test-make-release -b $RELEASE_TAG -d $BUILD_AND_DEVCHAIN_DIR - - protocol-test-matrix: - # Keeping name short because GitHub UI does not handle long names well - name: ${{ matrix.name }} - runs-on: ['self-hosted', 'monorepo-node18'] - timeout-minutes: 60 - needs: [install-dependencies, lint-checks] - if: | - github.base_ref == 'master' || contains(github.base_ref, 'staging') || contains(github.base_ref, 'production') || - contains(needs.install-dependencies.outputs.all_modified_files, 'packages/protocol') || - contains(needs.install-dependencies.outputs.all_modified_files, 'packages/sdk') || - contains(needs.install-dependencies.outputs.all_modified_files, 'packages/typescript') || - contains(needs.install-dependencies.outputs.all_modified_files, ',package.json') || - contains(needs.install-dependencies.outputs.all_modified_files, ',yarn.lock') || - false - strategy: - fail-fast: false - matrix: - include: - - name: Protocol Release Snapshots - command: | - yarn --cwd packages/protocol test:release-snapshots - if [[ $(git status packages/protocol/releaseData/versionReports --porcelain) ]]; then - git --no-pager diff packages/protocol/releaseData/versionReports - echo "There are git differences after generating release version report snapshots" - echo "If these changes are intended, update the 'releaseData/versionReports' accordingly" - exit 1 - fi - - name: Protocol Common tests - command: | - yarn --cwd packages/protocol test common/ - - name: Protocol Compatibility - command: | - yarn --cwd packages/protocol test compatibility/ - - name: Protocol Governance Network - command: | - yarn --cwd packages/protocol test governance/network/ - - name: Protocol Governance Validators - command: | - yarn --cwd packages/protocol test governance/validators/ - - name: Protocol Governance Voting - command: | - yarn --cwd packages/protocol test governance/voting/ - - name: Protocol Stability - command: | - yarn --cwd packages/protocol test stability/ - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Sync workspace - uses: ./.github/actions/sync-workspace - with: - rebuild-package: 'true' - artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }} - - name: Execute matrix command for test - uses: nick-fields/retry@v2 - with: - timeout_minutes: 40 - max_attempts: 3 - command: | - ${{ matrix.command }} - - contractkit-tests: - name: ContractKit Tests - runs-on: ['self-hosted', 'monorepo-node18'] - timeout-minutes: 30 - needs: [install-dependencies] - if: | - github.base_ref == 'master' || contains(github.base_ref, 'staging') || contains(github.base_ref, 'production') || - contains(needs.install-dependencies.outputs.all_modified_files, 'packages/protocol') || - contains(needs.install-dependencies.outputs.all_modified_files, 'packages/dev-utils') || - contains(needs.install-dependencies.outputs.all_modified_files, 'packages/sdk') || - contains(needs.install-dependencies.outputs.all_modified_files, 'packages/typescript') || - contains(needs.install-dependencies.outputs.all_modified_files, ',package.json') || - contains(needs.install-dependencies.outputs.all_modified_files, ',yarn.lock') || - false - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Sync workspace - uses: ./.github/actions/sync-workspace - with: - artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }} - - name: Run tests - run: | - yarn --cwd=packages/sdk/contractkit test - - cli-tests: - name: CeloCli Tests - runs-on: ['self-hosted', 'monorepo-node18'] - timeout-minutes: 30 - needs: [install-dependencies] - if: | - github.base_ref == 'master' || contains(github.base_ref, 'staging') || contains(github.base_ref, 'production') || - contains(needs.install-dependencies.outputs.all_modified_files, 'packages/cli') || - contains(needs.install-dependencies.outputs.all_modified_files, 'packages/protocol') || - contains(needs.install-dependencies.outputs.all_modified_files, 'packages/dev-utils') || - contains(needs.install-dependencies.outputs.all_modified_files, 'packages/sdk') || - contains(needs.install-dependencies.outputs.all_modified_files, 'packages/typescript') || - contains(needs.install-dependencies.outputs.all_modified_files, ',package.json') || - contains(needs.install-dependencies.outputs.all_modified_files, ',yarn.lock') || - false - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Sync workspace - uses: ./.github/actions/sync-workspace - with: - artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }} - - name: Run tests - run: | - yarn --cwd=packages/cli test - - name: Fail if someone forgot to commit CLI docs - run: | - yarn --cwd=packages/cli docs - if [[ $(git status packages/docs/command-line-interface --porcelain) ]]; then - git --no-pager diff packages/docs/command-line-interface - echo "There are git differences after generating CLI docs" - git status - git diff - exit 1 - fi - - name: Verify that a new account can be created - run: | - yarn --cwd=packages/cli run celocli account:new - - name: Test that releasecelo command topic is working - run: | - yarn --cwd=packages/cli run celocli releasecelo --help - typescript-tests: - name: Typescript package Tests - runs-on: ['self-hosted', 'monorepo-node18'] - timeout-minutes: 30 - needs: [install-dependencies] - if: | - github.base_ref == 'master' || contains(github.base_ref, 'staging') || contains(github.base_ref, 'production') || - contains(needs.install-dependencies.outputs.all_modified_files, 'packages/typescript') || - contains(needs.install-dependencies.outputs.all_modified_files, ',package.json') || - contains(needs.install-dependencies.outputs.all_modified_files, ',yarn.lock') || - false - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Sync workspace - uses: ./.github/actions/sync-workspace - with: - artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }} - - name: Install and test the npm package - run: | - set -euo pipefail - cd packages/typescript - yarn pack - cd $RUNNER_TEMP - npm install $RUNNER_WORKSPACE/celo-monorepo/packages/typescript/*.tgz - - base-test: - name: SDK Base package Tests - runs-on: ['self-hosted', 'monorepo-node18'] - timeout-minutes: 30 - needs: [install-dependencies] - if: | - github.base_ref == 'master' || contains(github.base_ref, 'staging') || contains(github.base_ref, 'production') || - contains(needs.install-dependencies.outputs.all_modified_files, 'packages/sdk') || - contains(needs.install-dependencies.outputs.all_modified_files, 'packages/typescript') || - contains(needs.install-dependencies.outputs.all_modified_files, ',package.json') || - contains(needs.install-dependencies.outputs.all_modified_files, ',yarn.lock') || - false - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Sync workspace - uses: ./.github/actions/sync-workspace - with: - artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }} - - name: Install and test the npm package - run: | - set -euo pipefail - cd packages/sdk/base - yarn pack - cd $RUNNER_TEMP - npm install $RUNNER_WORKSPACE/celo-monorepo/packages/sdk/base/*.tgz - - utils-test: - name: SDK Utils package Tests - runs-on: ['self-hosted', 'monorepo-node18'] - timeout-minutes: 30 - needs: [install-dependencies] - if: | - github.base_ref == 'master' || contains(github.base_ref, 'staging') || contains(github.base_ref, 'production') || - contains(needs.install-dependencies.outputs.all_modified_files, 'packages/sdk') || - contains(needs.install-dependencies.outputs.all_modified_files, 'packages/typescript') || - contains(needs.install-dependencies.outputs.all_modified_files, ',package.json') || - contains(needs.install-dependencies.outputs.all_modified_files, ',yarn.lock') || - false - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Sync workspace - uses: ./.github/actions/sync-workspace - with: - artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }} - - name: Install and test the npm package - run: | - set -euo pipefail - cd packages/sdk/base - yarn pack - cd ../utils - yarn pack - cd $RUNNER_TEMP - npm install $RUNNER_WORKSPACE/celo-monorepo/packages/sdk/base/*.tgz - npm install $RUNNER_WORKSPACE/celo-monorepo/packages/sdk/utils/*.tgz - - end-to-end-geth-matrix: - # Keeping name short because GitHub UI does not handle long names well - name: e2e ${{ matrix.name }} - runs-on: ['self-hosted', 'monorepo-node18'] - timeout-minutes: 60 - needs: [install-dependencies, lint-checks, contractkit-tests] - if: | - github.base_ref == 'master' || contains(github.base_ref, 'staging') || contains(github.base_ref, 'production') || - contains(needs.install-dependencies.outputs.all_modified_files, 'packages/celotool') || - contains(needs.install-dependencies.outputs.all_modified_files, 'packages/protocol') || - contains(needs.install-dependencies.outputs.all_modified_files, 'packages/dev-utils') || - contains(needs.install-dependencies.outputs.all_modified_files, 'packages/sdk') || - contains(needs.install-dependencies.outputs.all_modified_files, 'packages/typescript') || - contains(needs.install-dependencies.outputs.all_modified_files, ',package.json') || - contains(needs.install-dependencies.outputs.all_modified_files, ',yarn.lock') || - false - strategy: - fail-fast: false - matrix: - include: - - name: Transfer test - command: | - set -e - # Forcing to load go and rust paths - export PATH="/usr/local/go/bin:$HOME/.cargo/bin:${PATH}" - cd packages/celotool - ./ci_test_transfers.sh checkout ${CELO_BLOCKCHAIN_BRANCH_TO_TEST} - - name: Blockchain Parameters test - command: | - set -e - export PATH="/usr/local/go/bin:$HOME/.cargo/bin:${PATH}" - cd packages/celotool - ./ci_test_blockchain_parameters.sh checkout ${CELO_BLOCKCHAIN_BRANCH_TO_TEST} - - name: Slashing test - command: | - set -e - export PATH="/usr/local/go/bin:$HOME/.cargo/bin:${PATH}" - cd packages/celotool - ./ci_test_slashing.sh checkout ${CELO_BLOCKCHAIN_BRANCH_TO_TEST} - - name: Governance test - command: | - set -e - export PATH="/usr/local/go/bin:$HOME/.cargo/bin:${PATH}" - cd packages/celotool - ./ci_test_governance.sh checkout ${CELO_BLOCKCHAIN_BRANCH_TO_TEST} - - name: Replica test - command: | - set -e - export PATH="/usr/local/go/bin:$HOME/.cargo/bin:${PATH}" - cd packages/celotool - ./ci_test_replicas.sh checkout ${CELO_BLOCKCHAIN_BRANCH_TO_TEST} - - name: Sync test - command: | - set -e - export PATH="/usr/local/go/bin:$HOME/.cargo/bin:${PATH}" - cd packages/celotool - ./ci_test_sync.sh checkout ${CELO_BLOCKCHAIN_BRANCH_TO_TEST} - - name: CIP35 eth compatibility test - command: | - set -e - export PATH="/usr/local/go/bin:$HOME/.cargo/bin:${PATH}" - cd packages/celotool - echo "Test is skipped because migrations somehow fail" - # ./ci_test_cip35.sh checkout ${CELO_BLOCKCHAIN_BRANCH_TO_TEST} - - name: Validator order test - command: | - set -e - export PATH="/usr/local/go/bin:$HOME/.cargo/bin:${PATH}" - cd packages/celotool - - ./ci_test_validator_order.sh checkout ${CELO_BLOCKCHAIN_BRANCH_TO_TEST} - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Sync workspace - uses: ./.github/actions/sync-workspace - with: - artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }} - - name: Execute matrix command for test - uses: nick-fields/retry@v2 - with: - timeout_minutes: 30 - max_attempts: 3 - command: | - ${{ matrix.command }} - - # NOTE: This has not been fully tested as we don't have a license for certora - certora-test: - name: Certora test ${{ matrix.name }} - runs-on: ['self-hosted', 'monorepo-node18'] - timeout-minutes: 30 - needs: [install-dependencies, lint-checks] - # Disable as certora license is not active - if: | - false && ( - github.base_ref == 'master' || contains(github.base_ref, 'staging') || contains(github.base_ref, 'production') || - contains(needs.install-dependencies.outputs.all_modified_files, 'packages/protocol') || - contains(needs.install-dependencies.outputs.all_modified_files, 'packages/sdk') || - contains(needs.install-dependencies.outputs.all_modified_files, ',package.json') || - contains(needs.install-dependencies.outputs.all_modified_files, ',yarn.lock') - ) - env: - CERTORAKEY: NOT_ACTIVE - strategy: - fail-fast: false - matrix: - include: - - name: Locked Gold - command: | - cd packages/protocol - ./specs/scripts/lockedgold.sh - - name: Accounts - command: | - cd packages/protocol - ./specs/scripts/accounts.sh - - name: Accounts - command: | - cd packages/protocol - ./specs/scripts/accountsPrivileged.sh - - name: Accounts - command: | - cd packages/protocol - ./specs/scripts/applyHarness.sh - ./specs/scripts/governance.sh - - name: Accounts - command: | - cd packages/protocol - ./specs/scripts/reserve.sh - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Sync workspace - uses: ./.github/actions/sync-workspace - with: - artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }} - - uses: actions/setup-java@v3 - with: - distribution: 'zulu' - java-version: '11' - - name: Certora dependencies - run: | - echo "export PATH=$PATH:~/.local/bin" >> ~/.bashrc - sudo apt-get update - sudo apt-get install -y software-properties-common python3-pip - pip3 install certora-cli - wget https://github.com/ethereum/solidity/releases/download/v0.5.13/solc-static-linux - chmod +x solc-static-linux - sudo mv solc-static-linux /usr/bin/solc - - name: Build and run command - run: | - ${{ matrix.command }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..26608e409 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,301 @@ +name: Build & Test +run-name: 'Build & Test: ${{ github.head_ref || github.ref_name }}' + +# Dockefile for the self-hosted runner: +# https://github.com/celo-org/infrastructure/blob/master/terraform/root-modules/gcp/integration-tests-gke/files/github-arc/Dockerfile-monorepo + +on: + push: + branches: + - master + - changeset-release/master + pull_request: + branches: + - master + - new-main + - main + - 'release/**' + - 'prerelease/**' + +concurrency: + group: celo-monorepo-${{ github.ref }} + cancel-in-progress: true + +defaults: + run: + shell: bash --login -eo pipefail {0} + +env: + # Increment these to force cache rebuilding + NODE_MODULE_CACHE_VERSION: 5 + NODE_OPTIONS: '--max-old-space-size=4096' + TERM: dumb + +# EXAMPLE on debug ssh step +# - name: Setup tmate session +# uses: mxschmitt/action-tmate@v3 +# timeout-minutes: 20 +# if: contains(matrix.command, 'common/') && false +# with: +# limit-access-to-actor: true + +jobs: + install-dependencies: + name: Install dependencies + outputs: + # Propagate more outputs if you need https://github.com/tj-actions/changed-files#outputs + # Adding a initial comma so ',' matches also for the first file + all_modified_files: ',${{ steps.changed-files.outputs.all_modified_files }}' + artifacts_to_cache: ${{ steps.get_artifacts_to_cache.outputs.artifacts_to_cache }} + # runs-on: ubuntu-latest + runs-on: ['self-hosted', 'org', '8-cpu'] + container: + image: us-west1-docker.pkg.dev/devopsre/actions-runner-controller/celo-monorepo:node18 + timeout-minutes: 30 + steps: + - uses: actions/checkout@v4 + - name: Restore node cache + uses: actions/cache@v3 + id: cache_node + with: + # We need to cache all the artifacts generated by yarn install+build + # Update this list also in .github/actions/sync-workspace/action.yml with exactly the same list + path: | + node_modules + packages/**/node_modules + key: node-${{ runner.os }}-${{ runner.arch }}-${{ env.NODE_MODULE_CACHE_VERSION }}-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + node-${{ runner.os }}-${{ runner.arch }}-${{ env.NODE_MODULE_CACHE_VERSION }}- + - name: Install yarn dependencies + run: git config --global url."https://".insteadOf ssh:// && yarn install + if: steps.cache_node.outputs.cache-hit != 'true' + - name: Run yarn postinstall if cache hitted + run: yarn run postinstall + if: steps.cache_node.outputs.cache-hit == 'true' + - name: Build packages + run: yarn build --ignore docs --include-dependencies + - name: Check licenses + if: steps.cache_node.outputs.cache-hit != 'true' + run: | + yarn check-licenses + # Get workdir local changes and fail if there are any change + - name: Verify Changed files + id: verify-changed-files + uses: tj-actions/verify-changed-files@v16 + with: + fail-if-changed: 'true' + fail-message: 'Files changed during build. Please build locally and commit the changes.' + files: | + **/* + - run: | + echo "${{ steps.verify-changed-files.outputs.changed_files }}" + - name: Get the artifacts to cache + id: get_artifacts_to_cache + run: | + artifacts_to_cache="$(git ls-files --others --ignored --exclude-standard | grep -v node_modules | grep -v .js.map)" + echo "artifacts_to_cache<> $GITHUB_OUTPUT + echo "$artifacts_to_cache" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + # We use cache to share the build artifacts between jobs (gh artifacts are too slow...) + # For more context check https://github.com/actions/upload-artifact/issues/199 + - name: Restore build artifacts cache + uses: actions/cache@v3 + id: cache_build_artifacts + with: + # We need to cache all the artifacts generated by yarn install+build + # Update this list also in .github/actions/sync-workspace/action.yml with exactly the same list + path: | + ${{ steps.get_artifacts_to_cache.outputs.artifacts_to_cache }} + key: code-${{ github.sha }} + restore-keys: | + code-${{ github.sha }} + - name: Detect files changed in PR (or commit), and expose as output + id: changed-files + uses: tj-actions/changed-files@v37 + with: + # Using comma as separator to be able to easily match full paths (using ,) + separator: ',' + # Checking if changed in the last 100 commits in PRs + fetch_depth: '150' + - run: echo ",${{ steps.changed-files.outputs.all_modified_files }}" + + lint-checks: + name: Lint code + runs-on: ['self-hosted', 'org', '8-cpu'] + container: + image: us-west1-docker.pkg.dev/devopsre/actions-runner-controller/celo-monorepo:node18 + timeout-minutes: 30 + needs: install-dependencies + steps: + - uses: actions/checkout@v4 + - name: Sync workspace + uses: ./.github/actions/sync-workspace + with: + artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }} + - run: yarn run prettify:diff + - run: yarn run lint + general_test: + name: General jest test + runs-on: ['self-hosted', 'org', '8-cpu'] + container: + image: us-west1-docker.pkg.dev/devopsre/actions-runner-controller/celo-monorepo:node18 + needs: install-dependencies + steps: + - uses: actions/checkout@v4 + - name: Sync workspace + uses: ./.github/actions/sync-workspace + with: + artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }} + - name: Run Jest Tests + run: | + mkdir -p test-results/jest + # Skipping packages that are tested in a specific job below + yarn run lerna \ + --ignore @celo/contractkit \ + --ignore @celo/celocli \ + --ignore '@celo/wallet-*' \ + run test + - name: Upload Jest Test Results + uses: actions/upload-artifact@v3 + with: + name: Jest Test Results + path: test-results/jest + wallet-test: + name: Wallet test + runs-on: ['self-hosted', 'org', '8-cpu'] + container: + image: us-west1-docker.pkg.dev/devopsre/actions-runner-controller/celo-monorepo:node18 + timeout-minutes: 30 + needs: install-dependencies + steps: + - uses: actions/checkout@v4 + - name: Sync workspace + uses: ./.github/actions/sync-workspace + with: + artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }} + - name: Run Wallet tests + run: | + yarn run lerna --scope '@celo/wallet-*' run test + + contractkit-tests: + name: ContractKit Tests + runs-on: ['self-hosted', 'org', '8-cpu'] + container: + image: us-west1-docker.pkg.dev/devopsre/actions-runner-controller/celo-monorepo:node18 + timeout-minutes: 30 + needs: [install-dependencies] + if: | + github.base_ref == 'master' || contains(github.base_ref, 'release') || + contains(needs.install-dependencies.outputs.all_modified_files, 'packages/sdk') || + contains(needs.install-dependencies.outputs.all_modified_files, ',package.json') || + contains(needs.install-dependencies.outputs.all_modified_files, ',yarn.lock') || + false + steps: + - uses: actions/checkout@v4 + - name: Sync workspace + uses: ./.github/actions/sync-workspace + with: + artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }} + - name: Run tests + run: | + yarn --cwd=packages/sdk/contractkit test + + cli-tests: + name: CeloCli Tests + runs-on: ['self-hosted', 'org', '8-cpu'] + container: + image: us-west1-docker.pkg.dev/devopsre/actions-runner-controller/celo-monorepo:node18 + timeout-minutes: 30 + needs: [install-dependencies] + if: | + github.base_ref == 'master' || contains(github.base_ref, 'staging') || contains(github.base_ref, 'production') || + contains(needs.install-dependencies.outputs.all_modified_files, 'packages/cli') || + contains(needs.install-dependencies.outputs.all_modified_files, 'packages/sdk') || + contains(needs.install-dependencies.outputs.all_modified_files, 'packages/typescript') || + contains(needs.install-dependencies.outputs.all_modified_files, ',package.json') || + contains(needs.install-dependencies.outputs.all_modified_files, ',yarn.lock') || + false + steps: + - uses: actions/checkout@v4 + - name: Sync workspace + uses: ./.github/actions/sync-workspace + with: + artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }} + - name: Run tests + run: | + yarn --cwd=packages/cli test + - name: Fail if someone forgot to commit CLI docs + run: | + yarn --cwd=packages/cli docs + if [[ $(git status packages/docs/command-line-interface --porcelain) ]]; then + git --no-pager diff packages/docs/command-line-interface + echo "There are git differences after generating CLI docs" + git status + git diff + exit 1 + fi + - name: Verify that a new account can be created + run: | + yarn --cwd=packages/cli run celocli account:new + - name: Test that releasecelo command topic is working + run: | + yarn --cwd=packages/cli run celocli releasecelo --help + + base-test: + name: SDK Base package Tests + runs-on: ['self-hosted', 'org', '8-cpu'] + container: + image: us-west1-docker.pkg.dev/devopsre/actions-runner-controller/celo-monorepo:node18 + timeout-minutes: 30 + needs: [install-dependencies] + if: | + github.base_ref == 'master' || contains(github.base_ref, 'staging') || contains(github.base_ref, 'production') || + contains(needs.install-dependencies.outputs.all_modified_files, 'packages/sdk') || + contains(needs.install-dependencies.outputs.all_modified_files, 'packages/typescript') || + contains(needs.install-dependencies.outputs.all_modified_files, ',package.json') || + contains(needs.install-dependencies.outputs.all_modified_files, ',yarn.lock') || + false + steps: + - uses: actions/checkout@v4 + - name: Sync workspace + uses: ./.github/actions/sync-workspace + with: + artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }} + - name: Install and test the npm package + run: | + set -euo pipefail + cd packages/sdk/base + yarn pack + cd $RUNNER_TEMP + npm install $RUNNER_WORKSPACE/developer-tooling/packages/sdk/base/*.tgz + + utils-test: + name: SDK Utils package Tests + runs-on: ['self-hosted', 'org', '8-cpu'] + container: + image: us-west1-docker.pkg.dev/devopsre/actions-runner-controller/celo-monorepo:node18 + timeout-minutes: 30 + needs: [install-dependencies] + if: | + github.base_ref == 'master' || contains(github.base_ref, 'staging') || contains(github.base_ref, 'production') || + contains(needs.install-dependencies.outputs.all_modified_files, 'packages/sdk') || + contains(needs.install-dependencies.outputs.all_modified_files, 'packages/typescript') || + contains(needs.install-dependencies.outputs.all_modified_files, ',package.json') || + contains(needs.install-dependencies.outputs.all_modified_files, ',yarn.lock') || + false + steps: + - uses: actions/checkout@v4 + - name: Sync workspace + uses: ./.github/actions/sync-workspace + with: + artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }} + - name: Install and test the npm package + run: | + set -euo pipefail + cd packages/sdk/base + yarn pack + cd ../utils + yarn pack + cd $RUNNER_TEMP + npm install $RUNNER_WORKSPACE/developer-tooling/packages/sdk/base/*.tgz + npm install $RUNNER_WORKSPACE/developer-tooling/packages/sdk/utils/*.tgz diff --git a/.github/workflows/container-all-monorepo.yml b/.github/workflows/container-all-monorepo.yml deleted file mode 100644 index 682f64d73..000000000 --- a/.github/workflows/container-all-monorepo.yml +++ /dev/null @@ -1,42 +0,0 @@ ---- -name: Build celo-monorepo container - -on: - push: - paths: - - 'dockerfiles/all-monorepo/**' - branches: - - master - pull_request: - paths: - - 'dockerfiles/all-monorepo/**' - workflow_dispatch: - -jobs: - celomonorepo-build-dev: - uses: celo-org/reusable-workflows/.github/workflows/container-cicd.yaml@v1.8 - name: Build us-west1-docker.pkg.dev/devopsre/dev-images/monorepo:${{ github.sha }} - if: | - github.ref != 'refs/heads/master' - with: - workload-id-provider: projects/1094498259535/locations/global/workloadIdentityPools/gh-celo-monorepo/providers/github-by-repos - service-account: 'celo-monorepo-dev@devopsre.iam.gserviceaccount.com' - artifact-registry: us-west1-docker.pkg.dev/devopsre/dev-images/monorepo - tag: ${{ github.sha }} - context: . - file: dockerfiles/all-monorepo/Dockerfile - trivy: true - - celomonorepo-build: - uses: celo-org/reusable-workflows/.github/workflows/container-cicd.yaml@v1.8 - name: Build us-west1-docker.pkg.dev/devopsre/celo-monorepo/monorepo:${{ github.sha }} - if: | - github.ref == 'refs/heads/master' - with: - workload-id-provider: projects/1094498259535/locations/global/workloadIdentityPools/gh-celo-monorepo-master/providers/github-by-repos - service-account: 'celo-monorepo@devopsre.iam.gserviceaccount.com' - artifact-registry: us-west1-docker.pkg.dev/devopsre/celo-monorepo/monorepo - tag: ${{ github.sha }} - context: . - file: dockerfiles/all-monorepo/Dockerfile - trivy: true diff --git a/.github/workflows/container-celotool.yml b/.github/workflows/container-celotool.yml deleted file mode 100644 index 63e121c84..000000000 --- a/.github/workflows/container-celotool.yml +++ /dev/null @@ -1,42 +0,0 @@ ---- -name: Build celotool container - -on: - push: - paths: - - 'dockerfiles/celotool/**' - branches: - - master - pull_request: - paths: - - 'dockerfiles/celotool/**' - workflow_dispatch: - -jobs: - celotool-build-dev: - uses: celo-org/reusable-workflows/.github/workflows/container-cicd.yaml@v1.8 - name: Build us-west1-docker.pkg.dev/devopsre/dev-images/celotool:${{ github.sha }} - if: | - github.ref != 'refs/heads/master' - with: - workload-id-provider: projects/1094498259535/locations/global/workloadIdentityPools/gh-celo-monorepo/providers/github-by-repos - service-account: 'celo-monorepo-dev@devopsre.iam.gserviceaccount.com' - artifact-registry: us-west1-docker.pkg.dev/devopsre/dev-images/celotool - tag: ${{ github.sha }} - context: . - file: dockerfiles/celotool/Dockerfile - trivy: true - - celotool-build: - uses: celo-org/reusable-workflows/.github/workflows/container-cicd.yaml@v1.8 - name: Build us-west1-docker.pkg.dev/devopsre/celo-monorepo/celotool:${{ github.sha }} - if: | - github.ref == 'refs/heads/master' - with: - workload-id-provider: projects/1094498259535/locations/global/workloadIdentityPools/gh-celo-monorepo-master/providers/github-by-repos - service-account: 'celo-monorepo@devopsre.iam.gserviceaccount.com' - artifact-registry: us-west1-docker.pkg.dev/devopsre/celo-monorepo/celotool - tag: ${{ github.sha }} - context: . - file: dockerfiles/celotool/Dockerfile - trivy: true diff --git a/.github/workflows/container-circleci.yml b/.github/workflows/container-circleci.yml deleted file mode 100644 index 3ff53c3f2..000000000 --- a/.github/workflows/container-circleci.yml +++ /dev/null @@ -1,96 +0,0 @@ ---- -name: Build CircleCI related containers - -on: - push: - paths: - - 'dockerfiles/circleci/**' - branches: - - master - pull_request: - paths: - - 'dockerfiles/circleci/**' - workflow_dispatch: - -jobs: - changes: - runs-on: ubuntu-latest - outputs: - geth: ${{ steps.changes.outputs.geth }} - node12: ${{ steps.changes.outputs.node12 }} - gcloud: ${{ steps.changes.outputs.gcloud }} - steps: - - uses: actions/checkout@v3 - - name: Check for changes - uses: dorny/paths-filter@v2 - id: changes - with: - filters: | - geth: - - dockerfiles/circleci/Dockerfile - - dockerfiles/circleci/.dockerignore - node12: - - dockerfiles/circleci/circleci-node12/Dockerfile - gcloud: - - dockerfiles/circleci/node10-gcloud/Dockerfile - - geth-build-dev: - uses: celo-org/reusable-workflows/.github/workflows/container-cicd.yaml@v1.8 - name: Build us-west1-docker.pkg.dev/devopsre/dev-images/circleci-geth:testing - needs: changes - if: | - needs.changes.outputs.geth == 'true' && - github.ref != 'refs/heads/master' - with: - workload-id-provider: projects/1094498259535/locations/global/workloadIdentityPools/gh-celo-monorepo/providers/github-by-repos - service-account: 'celo-monorepo-dev@devopsre.iam.gserviceaccount.com' - artifact-registry: us-west1-docker.pkg.dev/devopsre/dev-images/circleci-geth - tag: testing - context: dockerfiles/circleci - trivy: true - - geth-build: - uses: celo-org/reusable-workflows/.github/workflows/container-cicd.yaml@v1.8 - name: Build us-west1-docker.pkg.dev/devopsre/celo-monorepo/circleci-geth:latest - needs: changes - if: | - needs.changes.outputs.geth == 'true' && - github.ref == 'refs/heads/master' - with: - workload-id-provider: projects/1094498259535/locations/global/workloadIdentityPools/gh-celo-monorepo-master/providers/github-by-repos - service-account: 'celo-monorepo@devopsre.iam.gserviceaccount.com' - artifact-registry: us-west1-docker.pkg.dev/devopsre/celo-monorepo/circleci-geth - tag: latest - context: dockerfiles/circleci - trivy: true - - node12-build-dev: - uses: celo-org/reusable-workflows/.github/workflows/container-cicd.yaml@v1.8 - name: Build us-west1-docker.pkg.dev/devopsre/dev-images/circleci-node12:testing - needs: changes - if: | - needs.changes.outputs.node12 == 'true' && - github.ref != 'refs/heads/master' - with: - workload-id-provider: projects/1094498259535/locations/global/workloadIdentityPools/gh-celo-monorepo/providers/github-by-repos - service-account: 'celo-monorepo-dev@devopsre.iam.gserviceaccount.com' - artifact-registry: us-west1-docker.pkg.dev/devopsre/dev-images/circleci-node12 - tag: testing - context: dockerfiles/circleci - trivy: true - - node12-build: - uses: celo-org/reusable-workflows/.github/workflows/container-cicd.yaml@v1.8 - name: Build us-west1-docker.pkg.dev/devopsre/celo-monorepo/circleci-node12:latest - needs: changes - if: | - needs.changes.outputs.node12 == 'true' && - github.ref == 'refs/heads/master' - with: - workload-id-provider: projects/1094498259535/locations/global/workloadIdentityPools/gh-celo-monorepo-master/providers/github-by-repos - service-account: 'celo-monorepo@devopsre.iam.gserviceaccount.com' - artifact-registry: us-west1-docker.pkg.dev/devopsre/celo-monorepo/circleci-node12 - tag: latest - context: dockerfiles/circleci - trivy: true - diff --git a/.github/workflows/container-cli.yml b/.github/workflows/container-cli.yml deleted file mode 100644 index 12a299442..000000000 --- a/.github/workflows/container-cli.yml +++ /dev/null @@ -1,42 +0,0 @@ ---- -name: Build celocli container - -on: - push: - paths: - - 'dockerfiles/cli-standalone/**' - branches: - - master - pull_request: - paths: - - 'dockerfiles/cli-standalone/**' - workflow_dispatch: - -jobs: - celocli-build-dev: - uses: celo-org/reusable-workflows/.github/workflows/container-cicd.yaml@v1.8 - name: Build us-west1-docker.pkg.dev/devopsre/dev-images/celocli:testing - if: | - github.ref != 'refs/heads/master' - with: - workload-id-provider: projects/1094498259535/locations/global/workloadIdentityPools/gh-celo-monorepo/providers/github-by-repos - service-account: 'celo-monorepo-dev@devopsre.iam.gserviceaccount.com' - artifact-registry: us-west1-docker.pkg.dev/devopsre/dev-images/celocli - tag: testing - context: . - file: dockerfiles/cli-standalone/Dockerfile - trivy: true - - celocli-build: - uses: celo-org/reusable-workflows/.github/workflows/container-cicd.yaml@v1.8 - name: Build us-west1-docker.pkg.dev/devopsre/celo-monorepo/celocli:latest - if: | - github.ref == 'refs/heads/master' - with: - workload-id-provider: projects/1094498259535/locations/global/workloadIdentityPools/gh-celo-monorepo-master/providers/github-by-repos - service-account: 'celo-monorepo@devopsre.iam.gserviceaccount.com' - artifact-registry: us-west1-docker.pkg.dev/devopsre/celo-monorepo/celocli - tag: latest - context: . - file: dockerfiles/cli-standalone/Dockerfile - trivy: true diff --git a/.github/workflows/cron-protocol-test-with-coverage.yml b/.github/workflows/cron-protocol-test-with-coverage.yml deleted file mode 100644 index e25e4ecd7..000000000 --- a/.github/workflows/cron-protocol-test-with-coverage.yml +++ /dev/null @@ -1,32 +0,0 @@ -# This tests are pretty slow and flacky -name: Protocol tests with coverage -# By default the sha where it runs is latest commit on default branch -# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#schedule -on: - schedule: - # Every Saturday at 13:00 UTC - - cron: 0 13 * * 6 - workflow_dispatch: - -jobs: - # This seems to take ages and last codecov report is from 2021-02-25 :/ - # https://app.codecov.io/gh/celo-org/celo-monorepo/commits - protocol-test-with-code-coverage: - runs-on: ["self-hosted", "monorepo-node18"] - steps: - - uses: actions/checkout@v3 - - name: Install yarn dependencies - run: yarn install - - name: Build packages - run: yarn build --ignore docs --include-dependencies - - name: Run protocol tests with coverage - run: yarn --cwd packages/protocol test:coverage - - name: Store results - uses: actions/upload-artifact@v3 - with: - name: protocol-coverage - path: packages/protocol/coverage - - name: Upload results to codecov - run: yarn codecov -F protocol - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/protocol-devchain.yml b/.github/workflows/protocol-devchain.yml deleted file mode 100644 index ce24d66e1..000000000 --- a/.github/workflows/protocol-devchain.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: 'CoreContracts: Devchain For Contract Release' -run-name: 'CoreContracts: Devchain For Contract Release' - -on: - schedule: - # monthly on 1 at 0:00 UTC - - cron: 0 0 1 * * - workflow_dispatch: - -jobs: - generate-protocol-devchain: - name: Generate protocol devchain used in celo-monorepo.yml workflow - runs-on: ['self-hosted', 'monorepo-node18'] - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - tag: core-contracts.v9 - node-version: 12 - - tag: core-contracts.v10 - node-version: 18 - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ matrix.tag }} - fetch-depth: 0 - submodules: recursive - - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node-version }} - - name: Install yarn dependencies - run: git config --global url."https://".insteadOf ssh:// && yarn install - - name: Build packages - run: yarn build --ignore docs --include-dependencies - # Workaround for https://stackoverflow.com/questions/72978485/git-submodule-update-failed-with-fatal-detected-dubious-ownership-in-repositor - # This is needed because some runners messup with permissions of git files and submodules. Particularly problematic for DinD runners (e.g. self-hosted+container arg) - - name: Configure git safe directories - run: git config --global --add safe.directory '*' - - name: Generate devchain of previous release - run: | - mkdir devchain - GRANTS_FILE=scripts/truffle/releaseGoldExampleConfigs.json - yarn --cwd packages/protocol devchain generate-tar devchain/devchain.tar.gz --release_gold_contracts $GRANTS_FILE - mv packages/protocol/build/contracts* devchain/ - - name: Upload devchain as artifact - uses: actions/upload-artifact@v3 - with: - name: devchain-${{ matrix.tag }} - path: devchain - # Max retention time is 90 days for public repos - # https://docs.github.com/en/actions/learn-github-actions/usage-limits-billing-and-administration#artifact-and-log-retention-policy - retention-days: 90 diff --git a/.github/workflows/protocol_tests.yml b/.github/workflows/protocol_tests.yml deleted file mode 100644 index 8a511a349..000000000 --- a/.github/workflows/protocol_tests.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: Protocol Foundry tests -on: [push, pull_request] - -jobs: - check: - defaults: - run: - working-directory: packages/protocol - name: Run tests - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - submodules: recursive - - name: Foundry cache - id: foundry-cache - uses: actions/cache@v3 - with: - path: ./cache - key: ${{ runner.os }}-foundry-cache - - name: Foundry out - id: foundry-out - uses: actions/cache@v3 - with: - path: ./out - key: ${{ runner.os }}-foundry-out - - - name: Install Foundry - uses: onbjerg/foundry-toolchain@v1 - with: - version: nightly - - - name: Install forge dependencies - run: forge install - - # "Run tests" already tries to compile the contracts - # Making it explicit here to have easier to read errors - - name: Compile Contracts - run: forge compile - - - name: Run tests - # can't use gas limit because some setUp function use more than the limit - run: forge test -vvv # --block-gas-limit 20000000 \ No newline at end of file diff --git a/.github/workflows/publish-contracts-abi-release.yml b/.github/workflows/publish-contracts-abi-release.yml deleted file mode 100644 index 7795e9d4c..000000000 --- a/.github/workflows/publish-contracts-abi-release.yml +++ /dev/null @@ -1,89 +0,0 @@ -name: Publish ABIs and Solidity files to NPM -on: - push: - branches: [main] - pull_request: - - release: - types: [released] - workflow_dispatch: - inputs: - npm_version: - description: 'NPM version' - required: true - type: string -jobs: - publish: - runs-on: ['self-hosted', 'org', 'npm-publish'] - permissions: - contents: write - id-token: write - pull-requests: write - repository-projects: write - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Akeyless Get Secrets - id: get_auth_token - uses: docker://us-west1-docker.pkg.dev/devopsre/akeyless-public/akeyless-action:latest - with: - api-url: https://api.gateway.akeyless.celo-networks-dev.org - access-id: p-kf9vjzruht6l - static-secrets: '{"/static-secrets/NPM/npm-publish-token":"NPM_TOKEN"}' - - # Setup .npmrc file to publish to npm - - uses: actions/setup-node@v3 - with: - node-version: '18.x' - registry-url: 'https://registry.npmjs.org' - #scope: '@celo' - - - name: 'Setup yarn' - shell: bash - run: | - npm install --global yarn - source ~/.bashrc - - - name: 'Install packages' - shell: bash - run: yarn - - - name: Check if a release should be published - # This is what sets the RELEASE_TYPE and RELEASE_VERSION env variables - run: yarn --silent is_contract_release >> "$GITHUB_ENV" - working-directory: packages/protocol - env: - GITHUB_TAG: ${{ github.ref_name }} - INPUT_VERSION: ${{ inputs.npm_version }} - - name: 'Build packages which will not need abis' - shell: bash - run: yarn build --ignore @celo/contractkit --ignore @celo/explorer --ignore @celo/celocli --ignore @celo/governance --ignore @celo/metadata-crawler --ignore @celo/celotool --ignore @celo/env-tests --ignore @celo/transactions-uri --ignore @celo/wallet-rpc --include-dependencies - - name: Compile solidity contracts and typescript files - run: yarn prepare_contracts_and_abis_publishing - working-directory: packages/protocol - env: - RELEASE_TYPE: ${{ env.RELEASE_TYPE }} - RELEASE_VERSION: ${{ env.RELEASE_VERSION }} - - - name: Publish @celo/contracts - run: | - cat package.json - npm publish $RELEASE_TYPE $DRY_RUN - working-directory: packages/protocol/contracts - env: - RELEASE_TYPE: --tag ${{ env.RELEASE_TYPE != '' && env.RELEASE_TYPE || 'canary' }} - RELEASE_VERSION: ${{ env.RELEASE_VERSION }} - NODE_AUTH_TOKEN: ${{ env.NPM_TOKEN }} - DRY_RUN: ${{ env.RELEASE_VERSION == '' && '--dry-run' || '' }} - - - name: Publish @celo/abis - run: | - cat package.json - npm publish $RELEASE_TYPE $DRY_RUN - working-directory: packages/protocol/abis - env: - RELEASE_TYPE: --tag ${{ env.RELEASE_TYPE != '' && env.RELEASE_TYPE || 'canary' }} - RELEASE_VERSION: ${{ env.RELEASE_VERSION }} - NODE_AUTH_TOKEN: ${{ env.NPM_TOKEN }} - DRY_RUN: ${{ env.RELEASE_VERSION == '' && '--dry-run' || '' }} diff --git a/.gitignore b/.gitignore index c81a7bffa..4921458db 100644 --- a/.gitignore +++ b/.gitignore @@ -94,17 +94,15 @@ packages/docs/_book/ .env.local # old packages -packages/reserve-site/* packages/blockchain-api/* -packages/mobile/* -packages/faucet/* -packages/moonpay-auth/* -packages/notification-service/* -packages/react-components/* packages/phone-number-privacy/* packages/sdk/identity/* packages/sdk/encrypted-backup/* - +packages/protocol/* +packages/celotool/* +packages/dev-utils/* +packages/metadata-crawler/* +packages/helm-charts/* # temp json file for deploy-sdks script scripts/failedSDKs.json diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 7eaacd704..000000000 --- a/.gitmodules +++ /dev/null @@ -1,15 +0,0 @@ -[submodule "packages/protocol/lib/celo-foundry"] - path = packages/protocol/lib/celo-foundry - url = https://github.com/celo-org/celo-foundry -[submodule "packages/protocol/lib/solidity-bytes-utils"] - path = packages/protocol/lib/solidity-bytes-utils - url = https://github.com/GNSPS/solidity-bytes-utils -[submodule "packages/protocol/lib/openzeppelin-contracts"] - path = packages/protocol/lib/openzeppelin-contracts - url = https://github.com/OpenZeppelin/openzeppelin-contracts -[submodule "packages/protocol/lib/mento-core"] - path = packages/protocol/lib/mento-core - url = https://github.com/mento-protocol/mento-core -[submodule "packages/protocol/lib/memview.sol"] - path = packages/protocol/lib/memview.sol - url = https://github.com/summa-tx/memview.sol diff --git a/.husky/pre-push b/.husky/pre-push index 9645bf67c..5eb282e36 100755 --- a/.husky/pre-push +++ b/.husky/pre-push @@ -2,12 +2,4 @@ . "$(dirname -- "$0")/_/husky.sh" -# recreate this as it was removed in husky -while read local_ref local_oid remote_ref remote_oid -do - HUSKY_GIT_STD="$local_ref $local_oid $remote_ref $remote_oid" -done - -HUSKY_GIT_STDIN=$HUSKY_GIT_STD node ./scripts/hooks/pre-push.js - bash scripts/hooks/prereleasecheck.sh diff --git a/.prettierignore b/.prettierignore index 269beb022..f267b654b 100644 --- a/.prettierignore +++ b/.prettierignore @@ -13,14 +13,6 @@ packages/**/lib packages/docs/_book -packages/protocol/build/ -packages/protocol/types/ -!packages/protocol/lib/**/*.ts -packages/protocol/scripts/**/*.js -packages/protocol/migrations/**/*.js -packages/protocol/test/**/*.js -packages/protocol/contractPackages.js -packages/protocol/abis/src-generated/ # prettier eats Latex underscore escapting and doesn't seem to have an option to disable packages/docs/celo-codebase/protocol/proof-of-stake/epoch-rewards.md diff --git a/.prettierrc.js b/.prettierrc.js index cf8fcbb7c..7f3a4d2de 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -6,12 +6,4 @@ module.exports = { printWidth: 100, tabWidth: 2, bracketSpacing: true, - overrides: [ - { - files: '**/*.sol', - options: { - singleQuote: false, - }, - }, - ], } diff --git a/.vscode/extensions.json b/.vscode/extensions.json index f24f6150e..9875906a0 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -7,12 +7,9 @@ "eamodio.gitlens", "ms-vscode.vscode-typescript-tslint-plugin", "esbenp.prettier-vscode", - "juanblanco.solidity", "redhat.vscode-yaml", "smkamranqadri.vscode-bolt-language", - "pkief.material-icon-theme", "davidanson.vscode-markdownlint", - "mikestead.dotenv", "coenraads.bracket-pair-colorizer-2", "markis.code-coverage" ], diff --git a/README.md b/README.md deleted file mode 100644 index ea5e9a098..000000000 --- a/README.md +++ /dev/null @@ -1,149 +0,0 @@ -

- - celo logo - -

- -**Celo Monorepo - Official repository for core projects comprising the Celo platform** - -This repository contains the source code for the Celo core projects including the [smart contracts](https://github.com/celo-org/celo-monorepo/tree/master/packages/protocol), [contractKit](https://github.com/celo-org/celo-monorepo/tree/master/packages/sdk/contractkit), -and other packages. The source code for the Celo Blockchain which operates a node on the Celo Network is kept in a separate repo [here](https://github.com/celo-org/celo-blockchain). - - - -[![GitHub Actions](https://github.com/celo-org/celo-monorepo/actions/workflows/container-all-monorepo.yml/badge.svg)](https://github.com/celo-org/celo-monorepo/actions/workflows/container-all-monorepo.yml) -[![Codecov](https://img.shields.io/codecov/c/github/celo-org/celo-monorepo)](https://codecov.io/gh/celo-org/celo-monorepo) -[![GitHub contributors](https://img.shields.io/github/contributors/celo-org/celo-monorepo)](https://github.com/celo-org/celo-monorepo/graphs/contributors) -[![GitHub commit activity](https://img.shields.io/github/commit-activity/w/celo-org/celo-monorepo)](https://github.com/celo-org/celo-monorepo/graphs/contributors) -[![GitHub Stars](https://img.shields.io/github/stars/celo-org/celo-monorepo.svg)](https://github.com/celo-org/celo-monorepo/stargazers) -![GitHub repo size](https://img.shields.io/github/repo-size/celo-org/celo-monorepo) -[![GitHub](https://img.shields.io/github/license/celo-org/celo-monorepo?color=blue)](https://github.com/celo-org/celo-monorepo/blob/master/LICENSE) - - - -[![Website celo.org](https://img.shields.io/website-up-down-green-red/https/celo.org.svg)](https://celo.org) -[![Blog](https://img.shields.io/badge/blog-up-green)](https://medium.com/celoorg) -[![docs](https://img.shields.io/badge/docs-up-green)](https://docs.celo.org/) -[![Youtube](https://img.shields.io/badge/YouTube%20channel-up-green)](https://www.youtube.com/channel/UCCZgos_YAJSXm5QX5D5Wkcw/videos?view=0&sort=p&flow=grid) -[![forum](https://img.shields.io/badge/forum-up-green)](https://forum.celo.org) -[![Discord](https://img.shields.io/discord/600834479145353243.svg)](https://discord.gg/RfHQKtY) -[![Twitter CeloDevs](https://img.shields.io/twitter/follow/celodevs?style=social)](https://twitter.com/celodevs) -[![Twitter CeloOrg](https://img.shields.io/twitter/follow/celoorg?style=social)](https://twitter.com/CeloOrg) -[![Subreddit subscribers](https://img.shields.io/reddit/subreddit-subscribers/CeloHQ?style=social)](https://www.reddit.com/r/CeloHQ/) - - - -[![GitHub pull requests by-label](https://img.shields.io/github/issues-pr-raw/celo-org/celo-monorepo)](https://github.com/celo-org/celo-monorepo/pulls) -[![GitHub Issues](https://img.shields.io/github/issues-raw/celo-org/celo-monorepo.svg)](https://github.com/celo-org/celo-monorepo/issues) -[![GitHub issues by-label](https://img.shields.io/github/issues/celo-org/celo-monorepo/1%20hour%20tasks)](https://github.com/celo-org/celo-monorepo/issues?q=is%3Aopen+is%3Aissue+label%3A%221+hour+tasks%22) - -Contents: - - - -- [Celo's Mission - Prosperity for All](#mission) -- [The Celo Stack](#stack) -- [Documentation](#docs) -- [Issues](#issues) -- [Repo Structure](#repo) -- [Contributing](#contributing) -- [Ask Questions, Find Answers, Get in Touch](#ask) -- [License](#license) - - -## 🥅 Celo's Mission - Prosperity for All - -Celo, pronounced /ˈtselo/, means ‘purpose’ in Esperanto. In a similar spirit, we are aiming to create a new platform to connect people globally and bring financial stability to those who need it most. We believe blockchain technology is one of the most exciting innovations in recent history and as a community we look to push the boundaries of what is possible with it today. More importantly, we are driven by purpose -- to solve real-world problems such as lack of access to sound currency, or friction for cash-transfer programs aimed to alleviate poverty. Our mission is to build a monetary system that creates the conditions for prosperity for all. - - -

- - Play on Youtube - What if money were beautiful - -
- What if money were beautiful? -

- -## 🧱 The Celo Stack - -Celo is oriented around providing the simplest possible experience for end users, who may have no familiarity with cryptocurrencies, and may be using low cost devices with limited connectivity. To achieve this, the project takes a full-stack approach, where each layer of the stack is designed with the end user in mind whilst considering other stakeholders \(e.g. operators of nodes in the network\) involved in enabling the end user experience. - -The Celo stack is structured into the following logical layers: - - -

- Celo protocol -
- The Celo Blockchain and Celo Core Contracts together comprise the Celo Protocol -

- -- **Celo Blockchain**: An open cryptographic protocol that allows applications to make transactions with and run smart contracts in a secure and decentralized fashion. The Celo Blockchain has shared ancestry with [Ethereum](https://www.ethereum.org), and maintains full EVM compatibility for smart contracts. However it uses a [Byzantine Fault Tolerant](http://pmg.csail.mit.edu/papers/osdi99.pdf) \(BFT\) consensus mechanism rather than Proof of Work, and has different block format, transaction format, client synchronization protocols, and gas payment and pricing mechanisms. The network’s native asset is Celo Gold, exposed via an ERC-20 interface. - -- **Celo Core Contracts**: A set of smart contracts running on the Celo Blockchain that comprise much of the logic of the platform features including ERC-20 stable currencies, identity attestations, Proof of Stake and governance. These smart contracts are upgradeable and managed by the decentralized governance process. - - -

- Celo network -
- Topology of a Celo Network -

- -- **Applications:** Applications for end users built on the Celo platform. The Celo Wallet app, the first of an ecosystem of applications, allows end users to manage accounts and make payments securely and simply by taking advantage of the innovations in the Celo protocol. Applications take the form of external mobile or backend software: they interact with the Celo Blockchain to issue transactions and invoke code that forms the Celo Core Contracts’ API. Third parties can also deploy custom smart contracts that their own applications can invoke, which in turn can leverage Celo Core Contracts. Applications may use centralized cloud services to provide some of their functionality: in the case of the Celo Wallet, push notifications and a transaction activity feed. - -## 📚 Documentation - -Follow the instructions in [SETUP.md](SETUP.md) to get a development environment set up. - -See [Developer's Guide](https://docs.celo.org/developer) for full details about the design of the Celo protocol and other information about running these projects. - -## 🙋 Issues - -See the [issue backlog](https://github.com/celo-org/celo-monorepo/issues) for a list of active or proposed tasks. Feel free to create new issues to report bugs and/or request features. - -## 📂 Repo Structure - -The repository has the following packages (sub projects): - -- [celotool](packages/celotool) - scripts for deploying and managing testnets -- [cli](packages/cli) - tool that uses ContractKit to interact with the Celo protocol ([docs](https://docs.celo.org/command-line-interface/introduction)) -- [dev-utils](packages/dev-utils) - a utils package for use as a dev dependency -- [docs](packages/docs) - technical documentation for the Celo project ([live](https://docs.celo.org/)) -- [helm-charts](packages/helm-charts) - (DEPRECATED) templatized deployments of entire environments to Kubernetes clusters. Check [celo-org/charts](https://github.com/celo-org/charts) instead. -- [protocol](packages/protocol) - identity, stability and other smart contracts for the Celo protocol ([docs](https://docs.celo.org/protocol)) -- [sdk](packages/sdk) - Typescript packages for interacting with Celo, including Contracts, Wallets, Crypto++ -- [contractkit](packages/sdk/contractkit) - library to help developers and validators interact with the protocol and its smart contracts ([docs](https://docs.celo.org/developer/contractkit)) -- [typescript](packages/typescript) - no README available (improve?) - -Code owners for each package can be found in [.github/CODEOWNERS](.github/CODEOWNERS). - -## ✍️ Contributing - -Feel free to jump on the Celo 🚂🚋🚋🚋. Improvements and contributions are highly encouraged! 🙏👊 - -See the [contributing guide](https://docs.celo.org/community/contributing) for details on how to participate. -[![GitHub issues by-label](https://img.shields.io/github/issues/celo-org/celo-monorepo/1%20hour%20tasks)](https://github.com/celo-org/celo-monorepo/issues?q=is%3Aopen+is%3Aissue+label%3A%221+hour+tasks%22) - -All communication and contributions to the Celo project are subject to the [Celo Code of Conduct](https://celo.org/code-of-conduct). - -Not yet ready to contribute but do like the project? Support Celo with a ⭐ or share the love in a [![Twitter URL](https://img.shields.io/twitter/url?style=social&url=https%3A%2F%2Fcelo.org%2F)](https://twitter.com/intent/tweet?url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DkKggE5OvyhE&via=celohq&text=Checkout%20celo%21%20Love%20what%20they%20are%20building.&hashtags=celo) - - - -## 💬 Ask Questions, Find Answers, Get in Touch - -- [Website](https://celo.org/) -- [Docs](https://docs.celo.org/) -- [Blog](https://medium.com/celohq) -- [YouTube](https://www.youtube.com/channel/UCCZgos_YAJSXm5QX5D5Wkcw/videos?view=0&sort=p&flow=grid) -- [Forum](https://forum.celo.org) -- [Discord](https://discord.gg/vRbExjv) -- [Twitter](https://twitter.com/CeloDevs) -- [Reddit](https://www.reddit.com/r/CeloHQ/) -- [Community Events](https://celo.org/community) - -## 📜 License - -All packages are licensed under the terms of the [Apache 2.0 License](LICENSE) unless otherwise specified in the LICENSE file at package's root. diff --git a/baklava_genesis_balances.json b/baklava_genesis_balances.json deleted file mode 100644 index 29039bd42..000000000 --- a/baklava_genesis_balances.json +++ /dev/null @@ -1,255 +0,0 @@ -{ - "value": "12000000000000000000000", - "addresses": [ - "028fad6c3142681c21517cd4414a6be4438f2556", - "0328b30dd55baa5a5fc1be23c4575a7fb779dc25", - "035ef01395e2cc1219482f0542a05b627fac36b6", - "0474fe22b801e5684ac54f65c2c5c34352c1e479", - "0537d935b50124b3bb9277d0356ce45400579c57", - "060b52f506579625ad73b99f1be8d6b06259953d", - "06d335ecd7ebe9a5bce97d7835de1fdf2858fa71", - "07894441a09086351ebb5b428a5717b7d2c7c592", - "07b5206afea553d49dbcffbbba23fca5896cc603", - "080d324a83ce58f99cb11535ae5e51f0b8374f8d", - "097623488573f87a02bbf292f9e78c0c751752e1", - "0ab74005a6017533d2f38f74bd029d18426bda0b", - "0b3654a18513c76eee3a576241f328a3514f26e8", - "0b3b9a58056d786e42a024225a507f26a6cd698c", - "0b993f51c1d60a68b9e55b03a0fbf4ab777cf6e7", - "0bcdf73c45d99f33d1d8354980d7ca73c4cf72db", - "0c0ae152fcbeabe3585198755ffe4f7d22bb5039", - "0c561cfe5616e01467ba9792f0bc320314c7b1c6", - "0e447c8d3369e0e95a081ddb9e4c181d56f3685e", - "0e5f835af9f0c32bd48b6540207844dd08bca3e9", - "0ebd974acb2dc4906508356a3f23c0701c4d9206", - "0f28312466e1a2190bdf458f43820c5a6b2a8292", - "10e7e7616304773bb6a6584ad7b7e9ae17cc8352", - "13b3e17f8cf507d8fee3532c3826d1b9d84d8bb2", - "1569c74093b9393ba5d5a684013458b1f3000185", - "1674e1f2c0b6d6f1b569f95795f623b76919bb91", - "192e049d4a4a0789dc964e1d46c2e3cd3b825480", - "19f79eaa92d20e0a2e7bf24e32fffc5a1239bc8c", - "1a7a7af9e78a690979963f1641f9694853226d0a", - "1b4ea26c03baea69e85e354af4c695be43a510d3", - "1dbe73b0480058106798adda62e25d5279233c1b", - "207202b4876e9452a3e10a0480b76d9f3ac6c4da", - "208767b8d773aec8fc56ab0345809b7fe56344de", - "21b3c28b7bd2b41fd78b181cf1a97b27e6ff2014", - "22031b9ba9c5fe20bedcf559e7d1966e2ff03173", - "255f0de37b99d52ad4189d06ab4f63a748b2d235", - "257105a729cedb5701dad1e0073ae751d0b788a1", - "27840F3C97F96311E9510EfCF9Ea28aC94e01f78", - "28c9c08659984625584e8df09e119b4d157f86aa", - "2947ea31ab65b1fee886dc6c113f79b222c804b7", - "29dd8b1a27f9381aea07f24c97f17e9df5442101", - "2c8a412026454d1e56b9687dd88d4a6080c10e87", - "2dc4051191c05c00821168256084455a5eb1ba1e", - "2ee2a7fd94a31cf1e6db3875f4fd3d961b15de17", - "2fbaaf12676191eab6bf9d92e84eabf11f303d7f", - "307501123022f0e78a523fffc40788ee2381ac22", - "30fd0740b4a6dfa31924982d377ee634b86d7a95", - "320ba815c2d43e44e6e7e8926d7c384cb4c12ea2", - "3216695f7a483f1275c419bb0d914412509821a0", - "333d3ad4628e36db96bec8b3292f41bace58fc33", - "3521a14aae3a4fac3c6d0d6ceb8642cdd21323a2", - "35537e972e63a72e6dcbd93d092110adee296ce5", - "3616626057d9012469ed3926e626ae8333904482", - "362f0dd270e96a8ab333c4283541fb15dc817126", - "3a60dfe47fb866306934d40e0934158e98ec8cea", - "3b63ae3002c0fab6e1481d4a33ec89650872b3d5", - "3cb7762c05231f62c5703849a685f0817073e2f2", - "3de7dddd7ea601097c78e874e914550c9ceb6950", - "3fba989dbd94d5742c5d27e241ef5472a940f8ff", - "412f2910970f81e49af9b46067d3fd4d7a281679", - "41716bcf7c9a97179a7a276b153a7563e5f777eb", - "43c8cc9884d8e2ea870c33bdc25f495c25f269df", - "43dda21951e06e5c70bd9196a49b2d2eb47018d8", - "4418a99ac82d042971668a78604d1baaa92b895f", - "44e11b8eb591a5b8b0cf4db6b02ad60e6ed89a62", - "44edd5027f894058cfb4b519beb04f247336bc22", - "4500b26a6f52836510bfd013241df203f03456f8", - "453f92064cd11cfc185b058757fd5ab23f98b978", - "48cedc58b10af13d688631bc3cb78a05b8a6e56a", - "49c3c6a9b0c17ac32169ffc45998aa80029128b3", - "4a36b1eeb0178c9948cffb183a2333e98ebb888d", - "4a47f329f9429ee621e6b359e46ff3b5ac79e5e7", - "4bacb36b23afb8d66dd1a85d5a0d3a4455db22ea", - "4d2f9739e6d82663bbd1fc3fd3cee041d631af7d", - "4d838eaefe4234307e66f8d3f3019bc305b0d1b5", - "4da496af48238fefea8b4ffe6183310750cca6ea", - "4dbda5f6d756b6288aa7a8be0d45a1644465c166", - "4df2ad5fbad3978b0330232c30b1a47f02303466", - "4e0585b243c3b434c846b050354cf216e76d1ee4", - "4f584db9ec38df930185df315d941d42b3186b9f", - "4f6e39afb99896f5f463eb516f9edde3361f1ac5", - "4f9f7fa5db4a44a469f95115e0525f548605c7fd", - "506423ab317013b94d1ddb2adc15cda413096987", - "522f59f216e9468cdb859a96f025348a237a4935", - "5279bd79792c588e2553c56580c3ab058809e67a", - "556b94105721e92331ef09e5689a72481a590dc1", - "5582268e275fc3407f92fa80dd3f0d05904a723a", - "558e42639b924b15a68982b52ae30e9e5505eaf7", - "575240f049aea7bc783f60bebd7fcb5584a54b4a", - "5862cf5a76efb0315d34de733e0300279add5d52", - "5a4b9e7bf6ff475c52e372025c5b161014f5f70d", - "5eee762a960560cb6a625f280e53f92d93ec9b78", - "608fe2dbe23917f523e157fe7d8044243417a1e8", - "60E8dd93413a473a7BF354E292057688F179E8c0", - "61a092b2d98d9f821e9089aae1d490bf77db1ce5", - "61d7e2d39b924744febc65d141f30e9f644bd286", - "62646f78bf550b801b619983747599e23deabe3a", - "62ced47f08c104920ffa023c8d8f75ff18fdfc1d", - "62f959f22dbe968d1a41d426ae9dad5596b93236", - "65c5bf635e57d6791a5a81fd64c186fc6b43f459", - "66d4902810a03f45015998a8e92be8e2fa49c05a", - "673ec125d05f8aa71f735407a87a14836d775512", - "675e639e4e19a22204bc1f5ea006e948413f796b", - "6835cd60eccbf73437e3a62cd460a52e1e9755fa", - "686ee1620230c237eef7963f68c9e5d29565a0e8", - "694fb0e26fc592984c8a310eb4fe9bcc3037ca48", - "69f52b7f0492889e18285f516b71cbaa1b67981f", - "6a2998527cd699982364c9399d17b63c6ca22a41", - "6a2beea75f32f2e7b264e9f25ac970c5210e9230", - "6af7f878dc47d3cd83507b760aba82af45c9f902", - "6bb1e8c0ecc1bdb3d6ce3b3359f2ffaa3cfb6f28", - "6c5035a2a6f4818d7451747f3ef5edfb8265e776", - "6d289a49d8e3fb5dc8c22be2648c57fcbb7e7ed2", - "6e580d964c7fb4338b59093b574950e3999bf9a6", - "6e80dea424a522b0257adc7fb3b8e7c6e29b02e5", - "6f46d495a492a212e330d20189a0656cf072836a", - "73b49da41223585a650712363ba7878ed60a964d", - "75bda3ac305484c50df6c66014b11eff13216f26", - "775a5c899fd4a7cdd54e9f41738087748cfcb953", - "77611f4e37c0fea6dbf9237c0549b5e4e231bf3f", - "7a914a1b9a025eca6a2c06936c94101184741ea2", - "7b8ce1efc66fb0730b95436d66d89a5b0888d656", - "7bf109e20bae23c8a68c3a975c9e3d7bea941658", - "7f53f21f0fd99983fc1d0d527ac5ff6fed52b9a0", - "818c54fe6ab2cec008ba64a7ec249f60b0c37a48", - "81a9cc4103e2c66a652b2c17baaf134fdaeafca9", - "84599e63cdf1f592a00be4c624587e1c59ff8ca0", - "8482688f494a359d9efe5c37c5e16071f97890bd", - "8792e294df1d75eaa215a2e6e18e9b28cfc48d07", - "87d7ca6e380fe9c785cab4d6ffc2bf7fec625855", - "89a2bb2f22e84aedf0c4152b9ef80cc2f015df51", - "8b4a3adeb377d478708aee2f0dacdaaf889845bc", - "8b5b77c229e405c33c7f99acbfb70b1f52c17462", - "8cc0160e1b17fb885cb918021621820642d87797", - "8fb800b94d2b1258236e598fcd5e65eaf45ca671", - "8fe0973e8e40cce79a142b7b1a9e5de987095adf", - "909adbc46da983140af4d4228e07b217f2ee5864", - "91d44695a988bf5ac192c8f1f0493d48724d15ad", - "91f5f037efdb97d0c7a840276837d4226b91a258", - "92fb67ace261e016678cd221972f21f5c03d781a", - "93c110dc9812dc075c1541b2c5d1030b2ad6c293", - "940f7e5e603377f58ffa019ea2ad7200c88c5086", - "94befc20ca6bb6b21a6e6d3757b6f2335675f65c", - "95785ce0ca05f23484342ca3c2337d7660b68d36", - "95b664befd3de2de8e8bdf1b1313aae02cc24d5b", - "96b473b7a71f1a3804ad306af4f07f86c796eff5", - "9880279fa2a2170b9f3d89181249a34a291e6547", - "99100ada9e90a4b1e8e7754fe6b4f3fb1d049113", - "9913e776ed11e9247ef89b4e8b2b7c062faa5281", - "9a9dbbb96fa2c49247360e5eacd72e80b6129458", - "9abd6739153d95512d0d68ec0960d296e2f174bc", - "9b6828d728ec0aedd7e8fe1da93979d66f70968b", - "9dba468122b12cd04bf4828c57f67a87fe03bbf0", - "9e60a9b6380562874c9bfc1d38bece0bcd1d9b30", - "9f51e74987043df2c2f461cabd7d1c93cd79f498", - "9f79acea4994cc09f31f2fc87105aa619fa22020", - "9f85baefb7942f8b6d03c28af32d09756830c1e8", - "a250b8d79653de86cf7431ff0719dc77fe08ccfb", - "a3e05f1152e832744047e231c7aea4e8cbb5db26", - "a5317a01d642fa1979056e886504513b28e31f05", - "a6db023dfb73785f3321cd409622e6b7df69e9b2", - "a866efed4e0af66a1fbf2c0cbc3e39197cbc5b01", - "a87c05c4598fcf6d7bb9f9e41ebaa05c2cb46abd", - "aace0cefe666cdf4d63f7b9d57a6e6cf5cf84d9f", - "ad67bae6526873c5a6df80639ac16d89e627641c", - "ae3aaffa0f2b5d8490bfa212c39a032852fb20de", - "aeac20cdb7f9cdda85ad09ac0920047e41bf0bcc", - "af8911392621c7881f4ef1a83021c651e0656f2a", - "b060351f01492a56287f0d9e07da18116c93728f", - "b0c9fa734e0fac63d9051554e869c33ebcfcec6d", - "b1beb7832f72b27d045a9078d8adb0a3e42b3f99", - "b1cb7ea2d15ef69d01aaf8185edbef0076d83454", - "b57bc132a8bd43cdb57f8d46f7f4c7ae18620e46", - "b584f6a8e1196b27592e3ec69446bed1b76d52d9", - "b7b3c854b00d65208e410a5d16eb54f58dbebbc7", - "b84fa68db82af1bfcbb4b876e017657afb1dd615", - "ba4d18be33b5d5f5a80fba1206c3e82944665d76", - "bcd25468e4d433ac442b87f32b37b39678bf7077", - "bf453cc91a56da43fe6ecb834679cb4522a8889d", - "bfea1fc9870ee47c517faf53da39edd9cb2142fa", - "c189de40c8af704581e80c5e74a79751ea6ca1e0", - "c1b1230bbf9590232e6d2d28c4c1c418a32339ef", - "c1c8432a07183e96043d00ce2a60d637cb509590", - "c2d5c2ac49fb7511584e567a48ef96917110ad9d", - "c37021cc0ec286891a203d19901b0572b7bead1d", - "c3a0ac447e6e2ba795cbdd8a3648cb2779203ea4", - "c50fbd7054e3eef480fb8c61a6a5798b3a8bcbbb", - "c53f5d047ea8a7725a4fd76002739d76548196f4", - "c5636b98fd6ddff3a7bb239e9729d75338e9a61f", - "c566b9f9b5551588b93a8bc00d34d2123d318ce3", - "c6034975ee23bb19685bffd3c4e818e964e0d7c7", - "c8c8e28dbe45a95b70d3f19b9a225b3531642a79", - "c9c349bb76a657f9210da350d664929c5946c90e", - "c9d6fe14d8e93269bd3487d1d1a7693ef60001e3", - "c9d9a8dbbc238ce17134dc9c12447dcc137630a7", - "ca21a04402913ad8a0c9fd05c48e7c5865b75ade", - "cad07ebf3c922bfe1292d4fbfce015a934e520b9", - "cbebe96dd4811243e23b1f7b43d7c3266c59af2f", - "cccd3999d5b421f906c4a35c0c95bcd533e1cfbb", - "cf08368e0aa6d6017a2fede771ea72abb555f266", - "cf5d9c9514e7217a19cd975cecc0257c9b69db1b", - "cf946b26fff0c2c1d3da93b7647034b90b5fcf99", - "d0604078265249629759f6f342cc5d19461b2c8b", - "d1d4c8b640ce83faf89c60bf47e7319f0ffe57f0", - "d4e068fb4467816c768fa3460ce9d5ae5642de37", - "d5c181972763b082d4d6ca84662878674c0bd35c", - "d660eb4c3d84beafe836e351d6c65f9cf62bd51f", - "d6f05649c5350c20030de1dc57ed31510141f487", - "d99bedef76c9caa7ec0cfdaa79c1b9330bb02061", - "db904be629d8d064238f65cc04e95166a36d9357", - "dbc52f9e934145e2e3172aead59303328bbad2d1", - "dbdb0c678342d4752c82df89ad8408902a55591a", - "dd30983c073d20116477ff672543e3eec3f491af", - "df155c157f2f53a653a6a62d0458647261514093", - "df917121efdc92e1ea4414731ad3fd5d07bde322", - "e01886c1c29f5e1ca8f6de0c02108967712ae216", - "e193d7ccb6d5644bff9c9bf41ff1e62765b382e8", - "e2b8269e836c0f2ede96802405410203fb0de3a6", - "e32c4fc7e75091197e7ce24f0b1257ea858c6a0d", - "e33722565fadde6225a26586f48d8625c50147c4", - "e49515934d5eb7e8a2df1f6b00a819de9938f2c6", - "e4c1da47b33abd25578becb8f90d2480d9575f89", - "e4dc20758df2b3dab5dbbfd3239ccdc0b9682206", - "e556d76384334a7138ca85e5eb4281c909628ae1", - "e59b4d7b0cf1a2b73a439894dc3d6fa08a53ce84", - "e5DE9f2d1535D5b2CF8D0BA91d1F92C475f88a3b", - "e609163306c42d60080c2c87e80881c4dc52e115", - "e6234077285ce68da7d6c62ec68894bd83a15398", - "e67a310436b8a3a23a994e4a0b29e8d82721be7c", - "e6f62ed66bf346e2dad9619c18c66e2a35c77da0", - "e7c85a3f18d18d40d713041a69d4795f36339f7d", - "e81ece7f8f962bd1076f1134d1fd523d64e43702", - "e820238dc7b75b7602dafc7ffccd35c9ef5e2fdf", - "e89897510bfb2fc0647325fb6d580594c061acbf", - "ea6a71634f7228798ec8ac6395525a632ec4945e", - "ea6f11e720ca72af1d8a94fff813617ee21be08e", - "ec4e104bd412aaea47c4ae753a8b3a194e9939ac", - "edf3dacb0fda9a955956cfc7f833ea4dbe26c4f2", - "ee9d99071e541e19eae7f1063539ef5b39199bd6", - "ef621af83c70695daac497d7959d2848c8a2acea", - "f327386ef9d6be057d1c720fef633938743660f3", - "f3ee14dfbbbb7f0ef1ef787be39bf4814741e300", - "f4691164b53141bd4082592c0e979689a0486500", - "f5b15312e6407988372d9280d064daa0248181be", - "f7084f320f3779dd2a92a2f58d23abb35f8a9c15", - "f75daae125083fca31583fef2d0a84e0344a1534", - "f823e8a4ba6adddb02e97b5b8886d18e41b2723e", - "fb92c612be9c9758d7111daa07954eb0455d224b", - "ff0559d9062650213623968d2bd4e25f8705910c", - "ffac3dcf14dc8e678204e2388031d4cc3e366261" - ] -} diff --git a/cloudbuild.yaml b/cloudbuild.yaml deleted file mode 100644 index 7c83c9d18..000000000 --- a/cloudbuild.yaml +++ /dev/null @@ -1,29 +0,0 @@ -# We use kaniko for building docker images -# More details: https://github.com/GoogleContainerTools/kaniko - -steps: - -- id: "docker:celotool" - name: gcr.io/kaniko-project/executor:v0.16.0 - args: [ - "--dockerfile=dockerfiles/celotool/Dockerfile", - "--cache=true", - "--destination=gcr.io/$PROJECT_ID/celo-monorepo:celotool-$COMMIT_SHA" - ] - waitFor: ['-'] - -- id: "docker:cli" - name: gcr.io/kaniko-project/executor:v0.16.0 - args: [ - "--dockerfile=dockerfiles/cli/Dockerfile", - "--cache=true", - "--destination=gcr.io/$PROJECT_ID/celocli:$COMMIT_SHA", - "--build-arg", - "celo_env=alfajores" - ] - waitFor: ['-'] - -options: - machineType: 'N1_HIGHCPU_8' - -timeout: 3000s \ No newline at end of file diff --git a/codecov.yml b/codecov.yml index fce14024b..4de04af97 100644 --- a/codecov.yml +++ b/codecov.yml @@ -11,12 +11,6 @@ coverage: celocli: paths: - packages/cli - odis: - paths: - - packages/phone-number-privacy - protocol: - paths: - - packages/protocol sdk: paths: - packages/sdk diff --git a/dependency-graph.json b/dependency-graph.json deleted file mode 100644 index 77db1a52d..000000000 --- a/dependency-graph.json +++ /dev/null @@ -1,244 +0,0 @@ -{ - "@celo/celotool": { - "location": "packages/celotool", - "dependencies": [ - "@celo/base", - "@celo/connect", - "@celo/contractkit", - "@celo/cryptographic-utils", - "@celo/dev-utils", - "@celo/env-tests", - "@celo/explorer", - "@celo/governance", - "@celo/network-utils", - "@celo/protocol", - "@celo/utils" - ] - }, - "@celo/celocli": { - "location": "packages/cli", - "dependencies": [ - "@celo/base", - "@celo/connect", - "@celo/contractkit", - "@celo/cryptographic-utils", - "@celo/dev-utils", - "@celo/explorer", - "@celo/governance", - "@celo/phone-utils", - "@celo/utils", - "@celo/wallet-hsm-azure", - "@celo/wallet-ledger", - "@celo/wallet-local" - ] - }, - "@celo/dev-utils": { - "location": "packages/dev-utils", - "dependencies": [] - }, - "@celo/env-tests": { - "location": "packages/env-tests", - "dependencies": [ - "@celo/base", - "@celo/connect", - "@celo/contractkit", - "@celo/cryptographic-utils", - "@celo/phone-utils", - "@celo/utils" - ] - }, - "@celo/metadata-crawler": { - "location": "packages/metadata-crawler", - "dependencies": [ - "@celo/connect", - "@celo/contractkit", - "@celo/utils" - ] - }, - "@celo/protocol": { - "location": "packages/protocol", - "dependencies": [ - "@celo/base", - "@celo/connect", - "@celo/cryptographic-utils", - "@celo/typescript", - "@celo/utils", - "@celo/wallet-local" - ] - }, - "@celo/typescript": { - "location": "packages/typescript", - "dependencies": [] - }, - "@celo/base": { - "location": "packages/sdk/base", - "dependencies": [ - "@celo/typescript" - ] - }, - "@celo/connect": { - "location": "packages/sdk/connect", - "dependencies": [ - "@celo/base", - "@celo/utils" - ] - }, - "@celo/contractkit": { - "location": "packages/sdk/contractkit", - "dependencies": [ - "@celo/base", - "@celo/connect", - "@celo/dev-utils", - "@celo/protocol", - "@celo/utils", - "@celo/wallet-local" - ] - }, - "@celo/cryptographic-utils": { - "location": "packages/sdk/cryptographic-utils", - "dependencies": [ - "@celo/base", - "@celo/typescript", - "@celo/utils" - ] - }, - "@celo/explorer": { - "location": "packages/sdk/explorer", - "dependencies": [ - "@celo/base", - "@celo/connect", - "@celo/contractkit", - "@celo/utils" - ] - }, - "@celo/governance": { - "location": "packages/sdk/governance", - "dependencies": [ - "@celo/base", - "@celo/connect", - "@celo/contractkit", - "@celo/explorer", - "@celo/utils" - ] - }, - "@celo/keystores": { - "location": "packages/sdk/keystores", - "dependencies": [ - "@celo/utils", - "@celo/wallet-local" - ] - }, - "@celo/network-utils": { - "location": "packages/sdk/network-utils", - "dependencies": [ - "@celo/dev-utils" - ] - }, - "@celo/phone-utils": { - "location": "packages/sdk/phone-utils", - "dependencies": [ - "@celo/base", - "@celo/typescript", - "@celo/utils" - ] - }, - "@celo/transactions-uri": { - "location": "packages/sdk/transactions-uri", - "dependencies": [ - "@celo/base", - "@celo/connect", - "@celo/contractkit", - "@celo/dev-utils" - ] - }, - "@celo/utils": { - "location": "packages/sdk/utils", - "dependencies": [ - "@celo/base", - "@celo/typescript" - ] - }, - "@celo/wallet-base": { - "location": "packages/sdk/wallets/wallet-base", - "dependencies": [ - "@celo/base", - "@celo/connect", - "@celo/utils" - ] - }, - "@celo/wallet-hsm-aws": { - "location": "packages/sdk/wallets/wallet-hsm-aws", - "dependencies": [ - "@celo/connect", - "@celo/utils", - "@celo/wallet-base", - "@celo/wallet-hsm", - "@celo/wallet-remote" - ] - }, - "@celo/wallet-hsm-azure": { - "location": "packages/sdk/wallets/wallet-hsm-azure", - "dependencies": [ - "@celo/base", - "@celo/connect", - "@celo/utils", - "@celo/wallet-base", - "@celo/wallet-hsm", - "@celo/wallet-remote" - ] - }, - "@celo/wallet-hsm-gcp": { - "location": "packages/sdk/wallets/wallet-hsm-gcp", - "dependencies": [ - "@celo/connect", - "@celo/utils", - "@celo/wallet-base", - "@celo/wallet-hsm", - "@celo/wallet-remote" - ] - }, - "@celo/wallet-hsm": { - "location": "packages/sdk/wallets/wallet-hsm", - "dependencies": [ - "@celo/base" - ] - }, - "@celo/wallet-ledger": { - "location": "packages/sdk/wallets/wallet-ledger", - "dependencies": [ - "@celo/base", - "@celo/connect", - "@celo/utils", - "@celo/wallet-base", - "@celo/wallet-remote" - ] - }, - "@celo/wallet-local": { - "location": "packages/sdk/wallets/wallet-local", - "dependencies": [ - "@celo/connect", - "@celo/utils", - "@celo/wallet-base" - ] - }, - "@celo/wallet-remote": { - "location": "packages/sdk/wallets/wallet-remote", - "dependencies": [ - "@celo/connect", - "@celo/utils", - "@celo/wallet-base" - ] - }, - "@celo/wallet-rpc": { - "location": "packages/sdk/wallets/wallet-rpc", - "dependencies": [ - "@celo/base", - "@celo/connect", - "@celo/contractkit", - "@celo/dev-utils", - "@celo/utils", - "@celo/wallet-base", - "@celo/wallet-remote" - ] - } -} \ No newline at end of file diff --git a/developer_key_publishing.md b/developer_key_publishing.md deleted file mode 100644 index f1a8e6f45..000000000 --- a/developer_key_publishing.md +++ /dev/null @@ -1,164 +0,0 @@ -# Developer Key Publishing - -In the development life cycle, there are a number of points where it is useful to have a published [public key](https://en.wikipedia.org/wiki/Public-key_cryptography). Examples include build signing, Git commit signing, and communicating with other community members securely. Build signing in particular is a required part of the release process for the Celo blockchain client. - -In support of these uses, [OpenPGP](https://www.openpgp.org/) public keys can be published to [celo.org](https://celo.org), where they can downloaded securely by anyone. - -If you want to read more about OpenPGP keys, including their structure and metadata, check out [Anatomy of a GPG Key by Dave Steele](https://davesteele.github.io/gpg/2014/09/20/anatomy-of-a-gpg-key/). - -> Note: This guide assumes you have an @clabs.co email address, but if you do not, simply change the email domain to your primary developer email (e.g. @example.com for alice@example.com) Some additional setup will be required in the DNS records for your domain to configure [OpenPGP WKD]((https://gnupg.org/blog/20161027-hosting-a-web-key-directory.html)). - -## Setup - -[GnuPG](https://gnupg.org), or `gpg`, is by far the most popular implementation of OpenPGP, and it is what we will be using here. - -Install `gpg` on MacOS with Homebrew using `brew install gpg` or visit [gnupg.org/download](https://gnupg.org/download/) for other options. - -#### Environment variables - -In this guide, a couple of environment variables are used in the commands. Set the following for convenience: - -```bash -export USER_NAME='your name on the clabs.co email domain. e.g. alice for alice@clabs.co' -export REAL_NAME='your first and last name. e.g. Alice Turing' -``` - -## Key Generation - -#### Algorithm -OpenPGP supports a number of cryptographic algorithms including [RSA](https://en.wikipedia.org/wiki/RSA_(cryptosystem)) and [ECC](https://en.wikipedia.org/wiki/Elliptic-curve_cryptography). - -Here we recommend `secp256k1`, which is the algorithm underlying identity on the Celo blockchain, because it is fast, secure, and promotes interoperability within the Celo ecosystem. (e.g. Your OpenPGP key could be used to take actions on-chain, which is pretty neat.) - -> Note: When using a YubiKey with firmware version less than 5.2.3, `secp256k1` is not available. Instead, we recommend using `rsa2048`. Github does have limited support for [signing algorithms](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/adding-a-new-gpg-key-to-your-github-account#supported-gpg-key-algorithms). - -#### User Identifier -In OpenPGP, each key is associated with a user identity, which is commonly an email address and your name (e.g. "Alice Turing "). A public key created by `gpg` will automatically include the username, in addition to the cryptographic public key information, so when someone downloads your public key, they will know it is intended for your email address. - -By publishing keys on [celo.org](https://celo.org), users can securely download developer keys from their `@clabs.co` email address, and know that it is the correct one because publishing to [celo.org](https://celo.org) requires approval of the Celo core developers. - -### On your YubiKey - -We recommend generating your developer key pair with a YubiKey. Generating your key on a YubiKey provides higher security by making it virtually impossible for an attacker to steal your private key by hacking your computer. - -> Warning: Losing your YubiKey will result in the permanent loss of any keys stored on it. It is not possible to create a backup of a private key created with this method. - -> Note: When asked for the admin PIN, it is 12345678 by default. If asked for the user PIN, it is 123456 by default. - -1. Insert the YubiKey into the USB port. -2. Run `gpg --card-edit --expert` -3. At the `gpg/card>` prompt, enter the following commands: - 1. `admin` - 2. `key-attr` - 1. `2` to select `ECC` on the signature key. - 2. `9` to select `secp256k1` on the signature key. - 3. Repeat this selection for the encryption and authentication keys. - 3. `generate` - 1. When asked if you want to backup your encryption key, specify `n` for no. - 2. Specify an expiration date, for example `2y` for 2 years. - 3. Enter you full name and `@clabs.co` email address when prompted. - 4. You may add a comment, but it is not required. - 4. `quit` - -See the [official YubiKey documentation](https://support.yubico.com/support/solutions/articles/15000006420-using-your-yubikey-with-openpgp) for more information. - -### On your machine - -Use the following command, replacing the environment variables, to generate a new key on your machine: - -```bash -gpg --quick-generate-key "${REAL_NAME} <${USER_NAME}@clabs.co>" secp256k1 -``` - -You now have a secret key and public key, on `secp256k1` and with a 2 year expiration, associated with your `@clabs.co` email address. - -See `man gpg` for more information on key generation options. - -#### Import to a Yubikey - -If you've generated a key on your local machine, it can be imported onto your YubiKey with the following steps. - -> Note: When asked for the admin PIN, it is 12345678 by default. If asked for the user PIN, it is 123456 by default. - -1. Insert the YubiKey into the USB port. -2. `gpg --edit-key ${USER_NAME}@clabs.co` -3. At the `gpg` prompt enter the following commands: - 1. `keytocard` and select `1` to set the signature key on the YubiKey. - 2. `keytocard` and select `3` to set the authentication key on the YubiKey. - 3. `quit` and save your changes. - -See the [official YubiKey documentation](https://support.yubico.com/support/solutions/articles/15000006420-using-your-yubikey-with-openpgp) - -#### Verify your signing key - -Use the following command as a quick way to verify that your new key can be used to produce a valid signature: - -```bash -gpg -u ${USER_NAME}@clabs.co -o - --sign <(head -c 256 /dev/urandom) | gpg --verify - -``` - -> Note: The command above works by signing 256 bytes of random data with your new key, then verifying the signature over that data. - -You should see `Good signature from ...` with your real name and email. - -## Key Publishing - -Keys are published to [celo.org](https://celo.org) using [OpenPGP WKD](https://gnupg.org/blog/20161027-hosting-a-web-key-directory.html), which is essentially just a hosted folder of public keys. Published keys are managed by submitting a pull request to the [https://github.com/celo-org/website](https://github.com/celo-org/website) repo on Github. - -#### Adding your key to the repository - -Adding your key to [https://github.com/celo-org/website](https://github.com/celo-org/website) repo will allow it to be available on [celo.org](https://celo.org) with the next website deployment. - -After cloning the repo, running the following command from the root of `website` will add your key to the `openpgpkey` directory: - -```bash -gpg --list-options show-only-fpr-mbox -k ${USER_NAME}@clabs.co | $(gpgconf --list-dirs libexecdir)/gpg-wks-client -v --install-key -C openpgpkey -``` - -You should confirm that a new key file was added to the `openpgpkey/` directory and open a pull request with the change. You should see the new file in the `openpgpkey/clabs.co/hu` folder, if you followed the directions above. - -#### Verifying the published key - -Once a new version of [celo.org](https://celo.org) is published, you will be able to verify your keys are published correctly with the key lookup instructions below. - -## Key Lookup - -Users can lookup keys on the `@clabs.co` domain with the following command: - -```bash -gpg --auto-key-locate wkd --locate-external-keys ${USER_NAME}@clabs.co -``` - -This command will query [clabs.co](https://clabs.co) over HTTPS and retrieve the latest key for `${USER_NAME}@clabs.co`. - -### Manually fetching a key - -If you want to check a key is correctly hosted, or want to fetch a key manualy for some reason, you can do so with: - -```bash -curl https://openpgpkey.clabs.co/.well-known/openpgpkey/clabs.co/hu/$USER_HASH -``` - -`$USER_HASH` can be obtained by observing the output of the WKD utility. It is the filename of the resulting key file that is added to the website repsitory for publishing. It can also be calculated directly following the specification in the WKD specification, [draft-koch-openpgp-webkey-service](https://datatracker.ietf.org/doc/draft-koch-openpgp-webkey-service/?include_text=1), section 3.1. (Warning: It uses an obscure varient of base32 :| ) - -## Document Signing - -A [signature](https://en.wikipedia.org/wiki/Digital_signature) can be produced over a document with a number of options using `gpg`. - -Use the following command to produce an ASCII encoded detached signature with your `@clabs.co` key: - -```bash -gpg -u ${USER_NAME}@clabs.co -o doc.txt.asc --armor --detach-sign doc.txt -``` - -This command will produce the signature file `doc.txt.asc` for `doc.txt`. The signature file can be distributed along side the document, and be verified by any user with access to the document and your public key. - -#### Signature Verification - -A signature file produced with the method above can be verified by any user that possesses your public key with the following command. - -```bash -gpg --verify doc.txt.asc doc.txt -``` - -See the `gpg` [manual entry on signatures](https://www.gnupg.org/gph/en/manual/x135.html) for more information. diff --git a/dockerfiles/all-monorepo/Dockerfile b/dockerfiles/all-monorepo/Dockerfile deleted file mode 100644 index 1b6a53ff1..000000000 --- a/dockerfiles/all-monorepo/Dockerfile +++ /dev/null @@ -1,26 +0,0 @@ -FROM node:18 -LABEL org.opencontainers.image.authors="devops@clabs.co" - -WORKDIR /celo-monorepo - -# Needed for gsutil -RUN apt-get update && \ - apt-get install -y lsb-release && \ - apt-get install -y curl build-essential git python3 && \ - export CLOUD_SDK_REPO="cloud-sdk-$(lsb_release -c -s)" && \ - echo "deb http://packages.cloud.google.com/apt $CLOUD_SDK_REPO main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list && \ - curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - && \ - apt-get update -y && \ - apt-get install -y google-cloud-sdk kubectl netcat-openbsd && \ - curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash && \ - rm -rf /var/lib/apt/lists/* - -# ensure yarn.lock is evaluated by kaniko cache diff -COPY . ./ - -RUN yarn install --network-timeout 100000 --frozen-lockfile && yarn cache clean -RUN yarn build - -RUN rm -rf .git -RUN rm -rf .gitmodules - diff --git a/dockerfiles/celotool/Dockerfile b/dockerfiles/celotool/Dockerfile deleted file mode 100644 index 6273c95fe..000000000 --- a/dockerfiles/celotool/Dockerfile +++ /dev/null @@ -1,75 +0,0 @@ -FROM node:18 -LABEL org.opencontainers.image.authors="devops@clabs.co" - -WORKDIR /celo-monorepo - -# Needed for gsutil -RUN apt-get update && \ - apt-get install -y lsb-release && \ - apt-get install -y curl build-essential git python3 && \ - export CLOUD_SDK_REPO="cloud-sdk-$(lsb_release -c -s)" && \ - echo "deb http://packages.cloud.google.com/apt $CLOUD_SDK_REPO main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list && \ - curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - && \ - apt-get update -y && \ - apt-get install -y google-cloud-sdk kubectl netcat-openbsd && \ - curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash && \ - rm -rf /var/lib/apt/lists/* - -RUN alias python=python3 - -# ensure yarn.lock is evaluated by kaniko cache diff -COPY lerna.json package.json yarn.lock ./ -COPY packages/celotool/package.json packages/celotool/ -COPY packages/dev-utils/package.json packages/dev-utils/ -COPY packages/env-tests/package.json packages/env-tests/package.json -COPY packages/protocol/package.json packages/protocol/ -COPY packages/sdk/base/package.json packages/sdk/base/ -COPY packages/sdk/connect/package.json packages/sdk/connect/ -COPY packages/sdk/contractkit/package.json packages/sdk/contractkit/ -COPY packages/sdk/cryptographic-utils/package.json packages/sdk/cryptographic-utils/ -COPY packages/sdk/explorer/package.json packages/sdk/explorer/ -COPY packages/sdk/governance/package.json packages/sdk/governance/ -COPY packages/sdk/network-utils/package.json packages/sdk/network-utils/ -COPY packages/sdk/utils/package.json packages/sdk/utils/ -COPY packages/sdk/wallets/wallet-base/package.json packages/sdk/wallets/wallet-base/ -COPY packages/sdk/wallets/wallet-local/package.json packages/sdk/wallets/wallet-local/ -COPY packages/typescript/package.json packages/typescript/ -COPY patches/ patches/ -COPY scripts/ scripts/ -COPY packages/sdk/phone-utils/package.json packages/sdk/phone-utils/package.json -# Makes build fail if it doesn't copy git, will be removed after build -COPY .git .git -COPY .gitmodules .gitmodules - -RUN yarn install --network-timeout 100000 --frozen-lockfile && yarn cache clean - -COPY packages/celotool packages/celotool/ -COPY packages/dev-utils packages/dev-utils/ -COPY packages/env-tests packages/env-tests -COPY packages/helm-charts packages/helm-charts -COPY packages/protocol packages/protocol/ -COPY packages/sdk/base packages/sdk/base/ -COPY packages/sdk/connect packages/sdk/connect/ -COPY packages/sdk/contractkit packages/sdk/contractkit/ -COPY packages/sdk/cryptographic-utils packages/sdk/cryptographic-utils/ -COPY packages/sdk/explorer packages/sdk/explorer/ -COPY packages/sdk/governance packages/sdk/governance/ -COPY packages/sdk/network-utils packages/sdk/network-utils/ -COPY packages/sdk/utils packages/sdk/utils/ -COPY packages/sdk/wallets/wallet-base packages/sdk/wallets/wallet-base/ -COPY packages/sdk/wallets/wallet-local packages/sdk/wallets/wallet-local/ -COPY packages/typescript packages/typescript/ -COPY packages/sdk/phone-utils packages/sdk/phone-utils/ - -RUN yarn build - -RUN rm -r .git -RUN rm .gitmodules - -ENV PATH="/celo-monorepo/packages/celotool/bin:${PATH}" - -COPY --from=golang:1.16-stretch /usr/local/go/ /usr/local/go/ - -ENV PATH="/usr/local/go/bin:${PATH}" - -CMD ["celotooljs.sh"] diff --git a/dockerfiles/circleci/.dockerignore b/dockerfiles/circleci/.dockerignore deleted file mode 100644 index 1d085cacc..000000000 --- a/dockerfiles/circleci/.dockerignore +++ /dev/null @@ -1 +0,0 @@ -** diff --git a/dockerfiles/circleci/Dockerfile b/dockerfiles/circleci/Dockerfile deleted file mode 100644 index 38f476477..000000000 --- a/dockerfiles/circleci/Dockerfile +++ /dev/null @@ -1,42 +0,0 @@ -FROM cimg/node:12.13 -LABEL org.opencontainers.image.authors="devops@clabs.co" - -RUN sudo apt-get update -y && \ - sudo apt-get install -y lsb-release libudev-dev libusb-dev libusb-1.0-0 - -# Install Kubernetes, as per https://kubernetes.io/docs/tasks/tools/install-kubectl/ -RUN sudo apt-get install -y apt-transport-https && \ - curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - && \ - echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee -a /etc/apt/sources.list.d/kubernetes.list && \ - sudo apt-get update && \ - sudo apt-get install -y kubectl - -RUN sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 467B942D3A79BD29 && \ - sudo apt-get update && \ - sudo apt-get install -y apt-transport-https ca-certificates curl gnupg && \ - echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] http://packages.cloud.google.com/apt cloud-sdk main" | \ - sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list && \ - curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | \ - sudo apt-key --keyring /usr/share/keyrings/cloud.google.gpg add - && \ - sudo apt-get update -y && \ - sudo apt-get install google-cloud-cli -y - -RUN sudo wget https://dl.google.com/go/go1.16.15.linux-amd64.tar.gz && \ - sudo tar xf go1.16.15.linux-amd64.tar.gz -C /usr/local && \ - sudo rm go1.16.15.linux-amd64.tar.gz - -RUN curl https://sh.rustup.rs -sSf | sh -s -- -y - -ENV PATH="/usr/local/go/bin:/home/circleci/.cargo/bin:${PATH}" - -RUN go version - -RUN rustup install 1.41.0 && \ - rustup default 1.41.0 - -RUN sudo apt-get clean -y && \ - sudo rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* - -RUN mkdir ~/.ssh/ && echo -e "Host github.com\n\tStrictHostKeyChecking no\n" > ~/.ssh/config - -CMD ["/bin/sh"] diff --git a/dockerfiles/circleci/circleci-node18/Dockerfile b/dockerfiles/circleci/circleci-node18/Dockerfile deleted file mode 100644 index c8ee05218..000000000 --- a/dockerfiles/circleci/circleci-node18/Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -FROM cimg/node:18.14.2 - -RUN sudo apt-get update -y -RUN sudo apt-get install lsb-release libudev-dev libusb-dev libusb-1.0-0 rsync -y - -# Install python3 and python2 -RUN sudo apt-get update -y && \ - sudo apt-get install -y python3 python2 && \ - # Set python3 as default - sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 1 && \ - sudo apt-get clean -y && \ - sudo rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* - -# Install Kubernetes, as per https://kubernetes.io/docs/tasks/tools/install-kubectl/ -RUN sudo apt-get install -y apt-transport-https && \ - curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - && \ - echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee -a /etc/apt/sources.list.d/kubernetes.list && \ - sudo apt-get update && \ - sudo apt-get install -y kubectl - -RUN echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list && \ - curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key --keyring /usr/share/keyrings/cloud.google.gpg add - && \ - sudo apt-get update && sudo apt-get install google-cloud-cli - -CMD ["/bin/sh"] diff --git a/dockerfiles/circleci/node10-gcloud/Dockerfile b/dockerfiles/circleci/node10-gcloud/Dockerfile deleted file mode 100644 index cab2e5c1c..000000000 --- a/dockerfiles/circleci/node10-gcloud/Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -FROM circleci/node:10 -MAINTAINER Gaston Ponti - -RUN sudo apt-get update -y -RUN sudo apt-get install lsb-release libudev-dev libusb-dev libusb-1.0-0 rsync -y - -# Install Kubernetes, as per https://kubernetes.io/docs/tasks/tools/install-kubectl/ -RUN sudo apt-get install -y apt-transport-https && \ - curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - && \ - echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee -a /etc/apt/sources.list.d/kubernetes.list && \ - sudo apt-get update && \ - sudo apt-get install -y kubectl - -RUN export CLOUD_SDK_REPO="cloud-sdk-$(lsb_release -c -s)" && \ - echo "deb http://packages.cloud.google.com/apt $CLOUD_SDK_REPO main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list && \ - curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - && \ - sudo apt-get update -y && sudo apt-get install google-cloud-sdk -y - -CMD ["/bin/sh"] \ No newline at end of file diff --git a/dockerfiles/cli-standalone/Dockerfile b/dockerfiles/cli-standalone/Dockerfile deleted file mode 100644 index 89a3759f0..000000000 --- a/dockerfiles/cli-standalone/Dockerfile +++ /dev/null @@ -1,29 +0,0 @@ -# Docker image containing the celocli, built from NPM. -# -# Example build command: -# -# VERSION=x.y.z; docker build . --build-arg VERSION=$VERSION -t gcr.io/celo-testnet/celocli-standalone:$VERSION -FROM node:12-alpine -LABEL org.opencontainers.image.authors="devops@clabs.co" - -# Install cli install dependencies. -RUN apk add --no-cache python3 git make gcc g++ bash libusb-dev linux-headers eudev-dev - -# Add an set as default a non-privileged user named celo. -RUN adduser -D -S celo -USER celo - -# Make folders for npm packages. -RUN mkdir /home/celo/.npm-global -ENV PATH=/home/celo/.npm-global/bin:$PATH -ENV NPM_CONFIG_PREFIX=/home/celo/.npm-global - -WORKDIR /home/celo/ - -# Install @celo/celocli from NPM. -ARG VERSION -RUN npm install -g @celo/celocli@$VERSION -RUN celocli config:set --node https://forno.celo.org - -ENTRYPOINT ["celocli"] -CMD ["--help"] diff --git a/dockerfiles/cli/Dockerfile b/dockerfiles/cli/Dockerfile deleted file mode 100644 index 1f7139131..000000000 --- a/dockerfiles/cli/Dockerfile +++ /dev/null @@ -1,70 +0,0 @@ -# Docker image for this file is hosted at -# us.gcr.io/celo-testnet/celocli:master -# -# How to test changes to this file -# docker build -f dockerfiles/cli/Dockerfile -t gcr.io/celo-testnet/celocli:$USER . --build-arg celo_env=alfajores -# To run this image locally -# docker rm cli_container; docker run --name cli_container -p 127.0.0.1:8545:8545 gcr.io/celo-testnet/celocli:$USER -v / -# To run this image locally in ultralight mode -# docker rm cli_container; docker run --name cli_container -p 127.0.0.1:8545:8545 -it --entrypoint=/celo/start_geth.sh gcr.io/celo-testnet/celocli:$USER "/usr/local/bin/geth" "alfajores" "full" -# and connect to it with -# docker exec -t -i cli_container /bin/sh -# -# Run commands against it using -# docker exec -it cli_container celocli -# For example, -# docker exec -it cli_container celocli account:balance 0x456f41406B32c45D59E539e4BBA3D7898c3584dA -# docker exec -it cli_container celocli account:balance 0xa0Af2E71cECc248f4a7fD606F203467B500Dd53B -# -# To restart -# docker start -ai cli_container -# -# To kill -# docker kill cli_container - -ARG geth_tag=1.7.4 -ARG geth_project=celo-org - -# Get geth and related files -FROM us.gcr.io/$geth_project/geth:$geth_tag as geth - -ARG celo_env -RUN echo "Env is ${celo_env}" && apk add curl && mkdir /celo -ADD https://www.googleapis.com/storage/v1/b/genesis_blocks/o/${celo_env}?alt=media /celo/genesis.json -ADD https://www.googleapis.com/storage/v1/b/static_nodes/o/${celo_env}?alt=media /celo/static-nodes.json - -# Build Celocli -FROM node:12-alpine as node - -ARG celo_env - -RUN echo "geth_tag is ${geth_tag}" && echo "Env is ${celo_env}" -# Required for celocli -RUN apk add --no-cache python git make gcc g++ pkgconfig libusb libusb-dev linux-headers eudev-dev - -WORKDIR /celo-monorepo/ -RUN npm install @celo/celocli - -# Build the combined image -FROM node:12-alpine as final_image -LABEL org.opencontainers.image.authors="devops@clabs.co" - -ARG network_name="alfajores" -ARG network_id="44787" - -# Without musl-dev, geth will fail with a confusing "No such file or directory" error. -# bash is required for start_geth.sh -RUN apk add --no-cache musl-dev bash - -WORKDIR /celo-monorepo/ - -RUN echo "Dir is ${PWD}" && echo "env is ${celo_env}" && mkdir /celo -COPY packages/cli/start_geth.sh /celo/start_geth.sh -COPY --from=geth /usr/local/bin/geth /usr/local/bin/geth -COPY --from=geth /celo/genesis.json /celo -COPY --from=geth /celo/static-nodes.json /celo -COPY --from=node /celo-monorepo/node_modules /celo-monorepo/node_modules -RUN chmod ugo+x /celo/start_geth.sh && ln -s /celo-monorepo/node_modules/.bin/celocli /usr/local/bin/celocli - -EXPOSE 8545 8546 30303 30303/udp -ENTRYPOINT ["/celo/start_geth.sh", "/usr/local/bin/geth", "alfajores", "full", "44787", "/root/.celo", "/celo/genesis.json", "/celo/static-nodes.json"] diff --git a/dockerfiles/cloudbuild/Dockerfile b/dockerfiles/cloudbuild/Dockerfile deleted file mode 100644 index 92a638ded..000000000 --- a/dockerfiles/cloudbuild/Dockerfile +++ /dev/null @@ -1,18 +0,0 @@ -FROM node:12 - -RUN apt-get update -y -RUN apt-get install lsb-release libudev-dev libusb-dev -y --no-install-recommends apt-utils - -# Install Kubernetes, as per https://kubernetes.io/docs/tasks/tools/install-kubectl/ -RUN apt-get install -y apt-transport-https && \ - curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - && \ - echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" | tee -a /etc/apt/sources.list.d/kubernetes.list && \ - apt-get update && \ - apt-get install -y kubectl - -RUN export CLOUD_SDK_REPO="cloud-sdk-$(lsb_release -c -s)" && \ - echo "deb http://packages.cloud.google.com/apt $CLOUD_SDK_REPO main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list && \ - curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - && \ - apt-get update -y && apt-get install google-cloud-sdk -y - -CMD ["/bin/sh"] diff --git a/dockerfiles/leaderboard/Dockerfile b/dockerfiles/leaderboard/Dockerfile deleted file mode 100644 index 2d8240ea8..000000000 --- a/dockerfiles/leaderboard/Dockerfile +++ /dev/null @@ -1,40 +0,0 @@ -FROM node:12 -WORKDIR /celo-monorepo - -# ensure yarn.lock is evaluated by kaniko cache diff -COPY lerna.json package.json yarn.lock ./ -COPY scripts/ scripts/ -COPY patches/ patches/ - -# Copy only pkg.json -COPY packages/typescript/package.json packages/typescript/ -COPY packages/sdk/base/package.json packages/sdk/base/ -COPY packages/sdk/utils/package.json packages/sdk/utils/ -COPY packages/dev-utils/package.json packages/dev-utils/ -COPY packages/sdk/connect/package.json packages/sdk/connect/ -COPY packages/sdk/wallets/wallet-base/package.json packages/sdk/wallets/wallet-base -COPY packages/sdk/wallets/wallet-local/package.json packages/sdk/wallets/wallet-local -COPY packages/protocol/package.json packages/protocol/ -COPY packages/sdk/contractkit/package.json packages/sdk/contractkit/ -COPY packages/leaderboard/package.json packages/leaderboard/ - -RUN yarn install --frozen-lockfile --network-timeout 100000 && yarn cache clean - -# Copy the rest -COPY packages/typescript packages/typescript/ -COPY packages/sdk/base packages/sdk/base/ -COPY packages/sdk/utils packages/sdk/utils/ -COPY packages/dev-utils packages/dev-utils/ -COPY packages/sdk/connect/package.json packages/sdk/connect/ -COPY packages/sdk/wallets/wallet-base packages/sdk/wallets/wallet-base -COPY packages/sdk/wallets/wallet-local packages/sdk/wallets/wallet-local -COPY packages/protocol packages/protocol/ -COPY packages/sdk/contractkit packages/sdk/contractkit/ -COPY packages/leaderboard packages/leaderboard/ - -# build all -RUN yarn build - -WORKDIR /celo-monorepo/packages/leaderboard - -CMD ["yarn run ts-node src/board.ts ; yarn run ts-node src/upload.ts"] diff --git a/package.json b/package.json index 8d661be53..53b75d094 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,6 @@ "private": true, "scripts": { "preinstall": "git config --global url.\"https://\".insteadOf ssh://", - "install-pkg": "yarn install --link-duplicates", "lint": "yarn lerna run lint && yarn run --silent lint:do-not-merge", "lint:do-not-merge": "! git grep -E 'DO[ _]*NOT[ _]*MERGE'", "prettify": "yarn run prettier --config .prettierrc.js --write '**/*.+(ts|tsx|js|jsx|sol|java)'", @@ -24,17 +23,12 @@ "check-licenses": "yarn licenses list --prod | grep '\\(─ GPL\\|─ (GPL-[1-9]\\.[0-9]\\+ OR GPL-[1-9]\\.[0-9]\\+)\\)' && echo 'Found GPL license(s). Use 'yarn licenses list --prod' to look up the offending package' || echo 'No GPL licenses found'", "report-coverage": "yarn run lerna run test-coverage", "test:watch": "node node_modules/jest/bin/jest.js --watch", - "postinstall": "yarn run lerna run postinstall && patch-package && yarn keys:decrypt", - "keys:decrypt": "bash scripts/key_placer.sh decrypt", - "keys:encrypt": "bash scripts/key_placer.sh encrypt", - "check:packages": "node ./scripts/check-packages.js", + "postinstall": "yarn run lerna run postinstall", "release": "yarn clean && yarn build && yarn --cwd packages/cli run prepack && yarn cs publish", "beta-enter": "bash scripts/beta-mode.sh", "beta-exit": "yarn changeset pre exit && git commit -am 'Complete beta mode'", "version-and-reinstall": "yarn changeset version && yarn install", - "celotool": "yarn --cwd packages/celotool run --silent cli", "celocli": "yarn --cwd packages/cli run --silent celocli", - "update-dependency-graph": "ts-node ./scripts/update_dependency_graph.ts", "deprecate-sdks": "ts-node ./scripts/unpublish-sdks.ts", "prepare": "husky install" }, @@ -43,10 +37,6 @@ "packages/*", "packages/sdk/*", "packages/sdk/wallets/*" - ], - "nohoist": [ - "**/openzeppelin-solidity", - "**/solidity-bytes-utils" ] }, "devDependencies": { @@ -59,9 +49,7 @@ "husky": "^8.0.0", "jest": "^29.0.2", "lerna": "^5.5.0", - "patch-package": "^6.2.2", "prettier": "^2.7.1", - "prettier-plugin-solidity": "1.0.0-alpha.35", "pretty-quick": "^2.0.1", "prompt": "1.2.0", "semver": "7.3.5", diff --git a/packages/celotool/.gitignore b/packages/celotool/.gitignore deleted file mode 100644 index 3aab66ec1..000000000 --- a/packages/celotool/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -/lib/ -.tmp - -twilio-config.js \ No newline at end of file diff --git a/packages/celotool/CHANGELOG.md b/packages/celotool/CHANGELOG.md deleted file mode 100644 index c58c315ce..000000000 --- a/packages/celotool/CHANGELOG.md +++ /dev/null @@ -1,116 +0,0 @@ -# @celo/celotool - -## 2.0.1 - -### Patch Changes - -- Updated dependencies [9ab9d00eb] -- Updated dependencies [1c9c844cf] -- Updated dependencies [9ab9d00eb] - - @celo/contractkit@6.0.0 - - @celo/env-tests@1.0.3 - - @celo/explorer@5.0.7 - - @celo/governance@5.0.7 - -## 2.0.1-beta.0 - -### Patch Changes - -- Updated dependencies [1c9c844cf] -- Updated dependencies [86bbfddf1] - - @celo/contractkit@6.0.0-beta.0 - - @celo/governance@5.0.7-beta.0 - - @celo/env-tests@1.0.3-beta.0 - - @celo/explorer@5.0.7-beta.0 - - -## 2.0.0 - -### Major Changes - -- 97d5ccf43: Remove lookup command, use `celocli identity:identifier --phoneNumber` - -### Patch Changes - -- 22ea7f691: Remove moment.js dependency -- Updated dependencies -- Updated dependencies [679ef0c60] -- Updated dependencies [32face3d8] -- Updated dependencies [22ea7f691] -- Updated dependencies [97d5ccf43] -- Updated dependencies [87647b46b] - - @celo/contractkit@5.2.0 - - @celo/connect@5.1.1 - - @celo/env-tests@1.0.2 - - @celo/base@6.0.0 - - @celo/cryptographic-utils@5.0.6 - - @celo/explorer@5.0.6 - - @celo/governance@5.0.6 - - @celo/utils@5.0.6 - -## 2.0.0-beta.0 - -### Major Changes - -- 97d5ccf43: Remove lookup command, use `celocli identity:identifier --phoneNumber` - -### Patch Changes - -- 22ea7f691: Remove moment.js dependency -- Updated dependencies -- Updated dependencies [32face3d8] -- Updated dependencies [22ea7f691] -- Updated dependencies [97d5ccf43] -- Updated dependencies [87647b46b] - - @celo/contractkit@5.2.0-beta.0 - - @celo/env-tests@1.0.2-beta.0 - - @celo/base@6.0.0-beta.0 - - @celo/explorer@5.0.6-beta.0 - - @celo/governance@5.0.6-beta.0 - - @celo/connect@5.1.1-beta.0 - - @celo/cryptographic-utils@5.0.6-beta.0 - - @celo/utils@5.0.6-beta.0 - -## 1.0.1 - -### Patch Changes - -- Updated dependencies [d48c68afc] -- Updated dependencies [d48c68afc] -- Updated dependencies [53bbd4958] -- Updated dependencies [d48c68afc] -- Updated dependencies [53bbd4958] -- Updated dependencies [d48c68afc] -- Updated dependencies [d48c68afc] -- Updated dependencies [d48c68afc] - - @celo/contractkit@5.1.0 - - @celo/connect@5.1.0 - - @celo/cryptographic-utils@5.0.5 - - @celo/governance@5.0.5 - - @celo/explorer@5.0.5 - - @celo/utils@5.0.5 - - @celo/base@5.0.5 - - @celo/network-utils@5.0.5 - - @celo/env-tests@1.0.1 - -## 1.0.1-beta.0 - -### Patch Changes - -- Updated dependencies [d48c68afc] -- Updated dependencies [d48c68afc] -- Updated dependencies [53bbd4958] -- Updated dependencies [d48c68afc] -- Updated dependencies [53bbd4958] -- Updated dependencies [d48c68afc] -- Updated dependencies [d48c68afc] -- Updated dependencies [d48c68afc] - - @celo/contractkit@5.1.0-beta.0 - - @celo/connect@5.1.0-beta.0 - - @celo/cryptographic-utils@5.0.5-beta.0 - - @celo/governance@5.0.5-beta.0 - - @celo/explorer@5.0.5-beta.0 - - @celo/utils@5.0.5-beta.0 - - @celo/base@5.0.5-beta.0 - - @celo/network-utils@5.0.5-beta.0 - - @celo/env-tests@1.0.1-beta.0 diff --git a/packages/celotool/README-e2e.md b/packages/celotool/README-e2e.md deleted file mode 100644 index bfef3698e..000000000 --- a/packages/celotool/README-e2e.md +++ /dev/null @@ -1,30 +0,0 @@ -# Celo-Blockchain End-to-End Tests - -This package contains a number of end-to-end tests that depend both on the -monorepo protocol package and the Golang celo-blockchain implementation. - -## Setup - -1. Run `yarn` to install node dependencies -2. Other dependencies: - 1. `nc`, the [netcat](https://en.wikipedia.org/wiki/Netcat) networking utility - -## Usage - -The tests are run using bash script wrappers. They are the -`ci_test_.sh` files in this package. Each requires a version of -celo-blockchain to be specified, which can be done in two ways. - -### Celo-blockchain built from local source - -``` -./ci_test_governance.sh local PATH -``` - -Where `PATH` is a path to a local source repository for celo-blockchain. - -### Celo-blockchain built from a specific GitHub branch - -``` -./ci_test_governance.sh checkout BRANCH -``` diff --git a/packages/celotool/README.md b/packages/celotool/README.md deleted file mode 100644 index 2a8614290..000000000 --- a/packages/celotool/README.md +++ /dev/null @@ -1,90 +0,0 @@ -# Celotool - -A useful tool for various scripts that we as an engineering team might run. -This is the only remaining version, in Typescript. There used to be a Python version too. -Hence the references to celotooljs. - -## Setup - -```bash -# Install packages -yarn -``` - -If you want to use this tool from anywhere, add an alias to your ~/.bash_profile. - -`alias celotooljs=/packages/celotool/bin/celotooljs.sh` - -## Usage - -Running `celotooljs` should give you the output like the following that let's you know what you can do: - -```bash - -celotooljs - -Commands: -celotooljs account commands for fauceting, - looking up accounts and users -celotooljs backup command for backing up a miner's - persistent volume (PVC) -celotooljs copy-contract-artifacts command for copying contract - artifacts in a format to be easily - consumed by other (typescript) - packages. It will use the ABI of a - particular contract and swap the - address for the address of the - Proxy. -celotooljs deploy commands for deployment of various - packages in the monorepo -celotooljs geth commands for geth -celotooljs links commands for various useful links -celotooljs port-forward command for port-forwarding to a - specific network -celotooljs restore command for restoring a miner's - persistent volume (PVC) from - snapshot -celotooljs switch command for switching to a - particular environment -celotooljs transactions commands for reading transaction - data -Options: ---version Show version number [boolean] ---verbose Whether to show a bunch of debugging output like stdout and - stderr of shell commands [boolean] [default: false] ---yesreally Reply "yes" to prompts about changing staging/production - (be careful!) [boolean] [default: false] - --help Show help [boolean] -``` - -### How to Faucet an Account - -Run this command: -`celotooljs account faucet --celo-env --account --gold 10 --dollar 10` - -### How to Setup a Local Celo Blockchain Node - -You might need to setup a local node for some reasons, therefore `celotooljs` provides you with -a few useful commands to make running a node really easy. - -- Clone [Celo Blockchain repo](https://github.com/celo-org/celo-blockchain) -- Build `celotooljs geth build --geth-dir -c` -- Init `celotooljs geth init --geth-dir --data-dir -e ` -- Run `celotooljs geth run --geth-dir --data-dir --sync-mode ` - -### How to Deploy a Test Network to the Cloud - -- Setup the environment variables: MNEMONIC, and GETH_ACCOUNT_SECRET. - -- Deploy: `celotooljs deploy initial testnet -e yourname` - -- Get pods: `kubectl get pods -n yourname` - -- Start shell: `kubectl exec -n podname -it podname /bin/sh` - -- Tear down: `celotooljs deploy destroy testnet -e yourname` - -#### MacOS Setup - -- Install Helm 3.4 or higher (available on Homebrew) - To get past the Unidentified Developer error: open the directory containing helm, then ctrl-click helm and select Open then Open again. Repeat for tiller. diff --git a/packages/celotool/bin/celotooljs.sh b/packages/celotool/bin/celotooljs.sh deleted file mode 100755 index 9692a4fb9..000000000 --- a/packages/celotool/bin/celotooljs.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -cd $(dirname $0) -yarn run --silent cli "$@" diff --git a/packages/celotool/ci_test_blockchain_parameters.sh b/packages/celotool/ci_test_blockchain_parameters.sh deleted file mode 100755 index 032c8fd73..000000000 --- a/packages/celotool/ci_test_blockchain_parameters.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# This tests that the geth node will exit if its version is too low - -# For testing a particular branch of Geth repo (usually, on Circle CI) -# Usage: ci_test_exit.sh checkout -# For testing the local Geth dir (usually, for manual testing) -# Usage: ci_test_exit.sh local - -export TS_NODE_FILES=true -if [ "${1}" == "checkout" ]; then - # Test master by default. - BRANCH_TO_TEST=${2:-"master"} - echo "Checking out geth at branch ${BRANCH_TO_TEST}..." - ./node_modules/.bin/mocha --node-option loader=ts-node/esm src/e2e-tests/blockchain_parameters_tests.ts --branch ${BRANCH_TO_TEST} -elif [ "${1}" == "local" ]; then - export GETH_DIR="${2}" - echo "Testing using local geth dir ${GETH_DIR}..." - ./node_modules/.bin/mocha --node-option loader=ts-node/esm src/e2e-tests/blockchain_parameters_tests.ts --localgeth ${GETH_DIR} -fi diff --git a/packages/celotool/ci_test_cip35.sh b/packages/celotool/ci_test_cip35.sh deleted file mode 100755 index 5001c52c5..000000000 --- a/packages/celotool/ci_test_cip35.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# This tests that the geth node will exit if its version is too low - -# For testing a particular branch of Geth repo (usually, on Circle CI) -# Usage: ci_test_exit.sh checkout -# For testing the local Geth dir (usually, for manual testing) -# Usage: ci_test_exit.sh local - -export TS_NODE_FILES=true -if [ "${1}" == "checkout" ]; then - # Test master by default. - BRANCH_TO_TEST=${2:-"master"} - echo "Checking out geth at branch ${BRANCH_TO_TEST}..." - ./node_modules/.bin/mocha --node-option loader=ts-node/esm src/e2e-tests/cip35_tests.ts --branch ${BRANCH_TO_TEST} -elif [ "${1}" == "local" ]; then - export GETH_DIR="${2}" - echo "Testing using local geth dir ${GETH_DIR}..." - ./node_modules/.bin/mocha --node-option loader=ts-node/esm src/e2e-tests/cip35_tests.ts --localgeth ${GETH_DIR} -fi diff --git a/packages/celotool/ci_test_governance.sh b/packages/celotool/ci_test_governance.sh deleted file mode 100755 index 27cfd5bdf..000000000 --- a/packages/celotool/ci_test_governance.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# This test starts a standalone Geth node and runs transactions on it. - -# For testing a particular branch of Geth repo (usually, on Circle CI) -# Usage: ci_test_governance.sh checkout -# For testing the local Geth dir (usually, for manual testing) -# Usage: ci_test_governance.sh local - -export TS_NODE_FILES=true -if [ "${1}" == "checkout" ]; then - # Test master by default. - BRANCH_TO_TEST=${2:-"master"} - echo "Checking out geth at branch ${BRANCH_TO_TEST}..." - ./node_modules/.bin/mocha --node-option loader=ts-node/esm src/e2e-tests/governance_tests.ts --branch ${BRANCH_TO_TEST} -elif [ "${1}" == "local" ]; then - export GETH_DIR="${2}" - echo "Testing using local geth dir ${GETH_DIR}..." - ./node_modules/.bin/mocha --node-option loader=ts-node/esm src/e2e-tests/governance_tests.ts --localgeth ${GETH_DIR} -fi diff --git a/packages/celotool/ci_test_replicas.sh b/packages/celotool/ci_test_replicas.sh deleted file mode 100755 index 469c3bbed..000000000 --- a/packages/celotool/ci_test_replicas.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# This test tests rotating validators with zero downtime. - -# For testing a particular branch of Geth repo (usually, on Circle CI) -# Usage: ci_test_replicas.sh checkout -# For testing the local Geth dir (usually, for manual testing) -# Usage: ci_test_replicas.sh local - -export TS_NODE_FILES=true -if [ "${1}" == "checkout" ]; then - # Test master by default. - BRANCH_TO_TEST=${2:-"master"} - echo "Checking out geth at branch ${BRANCH_TO_TEST}..." - ./node_modules/.bin/mocha --node-option loader=ts-node/esm src/e2e-tests/replica_tests.ts --branch ${BRANCH_TO_TEST} -elif [ "${1}" == "local" ]; then - export GETH_DIR="${2}" - echo "Testing using local geth dir ${GETH_DIR}..." - ./node_modules/.bin/mocha --node-option loader=ts-node/esm src/e2e-tests/replica_tests.ts --localgeth ${GETH_DIR} -fi diff --git a/packages/celotool/ci_test_slashing.sh b/packages/celotool/ci_test_slashing.sh deleted file mode 100755 index e350181c9..000000000 --- a/packages/celotool/ci_test_slashing.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Slashing tests - -# For testing a particular branch of Geth repo (usually, on Circle CI) -# Usage: ci_test_exit.sh checkout -# For testing the local Geth dir (usually, for manual testing) -# Usage: ci_test_exit.sh local - -export TS_NODE_FILES=true -if [ "${1}" == "checkout" ]; then - # Test master by default. - BRANCH_TO_TEST=${2:-"master"} - echo "Checking out geth at branch ${BRANCH_TO_TEST}..." - ./node_modules/.bin/mocha --node-option loader=ts-node/esm src/e2e-tests/slashing_tests.ts --branch ${BRANCH_TO_TEST} -elif [ "${1}" == "local" ]; then - export GETH_DIR="${2}" - echo "Testing using local geth dir ${GETH_DIR}..." - ./node_modules/.bin/mocha --localgeth ${GETH_DIR} --node-option loader=ts-node/esm,experimental-specifier-resolution=node ./src/e2e-tests/slashing_tests.ts -fi diff --git a/packages/celotool/ci_test_sync.sh b/packages/celotool/ci_test_sync.sh deleted file mode 100755 index 261e843bd..000000000 --- a/packages/celotool/ci_test_sync.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# This test starts a Geth mining node and checks that other nodes can sync with it. - -# For testing a particular branch of Geth repo (usually, on Circle CI) -# Usage: ci_test_sync.sh checkout -# For testing the local Geth dir (usually, for manual testing) -# Usage: ci_test_sync.sh local - -export TS_NODE_FILES=true -if [ "${1}" == "checkout" ]; then - # Test master by default. - BRANCH_TO_TEST=${2:-"master"} - echo "Checking out geth at branch ${BRANCH_TO_TEST}..." - ./node_modules/.bin/mocha --node-option loader=ts-node/esm src/e2e-tests/sync_tests.ts --branch ${BRANCH_TO_TEST} -elif [ "${1}" == "local" ]; then - export GETH_DIR="${2}" - echo "Testing using local geth dir ${GETH_DIR}..." - ./node_modules/.bin/mocha --node-option loader=ts-node/esm src/e2e-tests/sync_tests.ts --localgeth ${GETH_DIR} -fi diff --git a/packages/celotool/ci_test_transfers.sh b/packages/celotool/ci_test_transfers.sh deleted file mode 100755 index ab91e4734..000000000 --- a/packages/celotool/ci_test_transfers.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# This test starts a standalone Geth node and runs transactions on it. - -# For testing a particular branch of Geth repo (usually, on Circle CI) -# Usage: ci_test_transfers.sh checkout -# For testing the local Geth dir (usually, for manual testing) -# Usage: ci_test_transfers.sh local - -export TS_NODE_FILES=true -if [ "${1}" == "checkout" ]; then - # Test master by default. - BRANCH_TO_TEST=${2:-"master"} - echo "Checking out geth at branch ${BRANCH_TO_TEST}..." - ./node_modules/.bin/mocha --node-option loader=ts-node/esm src/e2e-tests/transfer_tests.ts --branch ${BRANCH_TO_TEST} -elif [ "${1}" == "local" ]; then - export GETH_DIR="${2}" - echo "Testing using local geth dir ${GETH_DIR}..." - ./node_modules/.bin/mocha --node-option loader=ts-node/esm src/e2e-tests/transfer_tests.ts --localgeth ${GETH_DIR} -fi diff --git a/packages/celotool/ci_test_validator_order.sh b/packages/celotool/ci_test_validator_order.sh deleted file mode 100755 index 7a70bf2e8..000000000 --- a/packages/celotool/ci_test_validator_order.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# This test starts a standalone Geth node and runs transactions on it. - -# For testing a particular branch of Geth repo (usually, on Circle CI) -# Usage: ci_test_validator_order.sh checkout -# For testing the local Geth dir (usually, for manual testing) -# Usage: ci_test_validator_order.sh local - -export TS_NODE_FILES=true -if [ "${1}" == "checkout" ]; then - # Test master by default. - BRANCH_TO_TEST=${2:-"master"} - echo "Checking out geth at branch ${BRANCH_TO_TEST}..." - ./node_modules/.bin/mocha --node-option loader=ts-node/esm src/e2e-tests/validator_order_tests.ts --branch ${BRANCH_TO_TEST} -elif [ "${1}" == "local" ]; then - export GETH_DIR="${2}" - echo "Testing using local geth dir ${GETH_DIR}..." - ./node_modules/.bin/mocha --node-option loader=ts-node/esm src/e2e-tests/validator_order_tests.ts --localgeth ${GETH_DIR} -fi diff --git a/packages/celotool/cloudbuild.yaml b/packages/celotool/cloudbuild.yaml deleted file mode 100644 index 8dad1f34c..000000000 --- a/packages/celotool/cloudbuild.yaml +++ /dev/null @@ -1,16 +0,0 @@ -steps: - -# Unshallow clone -- name: gcr.io/cloud-builders/git - args: ['fetch', '--unshallow'] - -# build docker image for google container registry -- name: gcr.io/kaniko-project/executor:latest - args: [ - "--dockerfile=dockerfiles/monorepo/Dockerfile.celotool", - "--cache=true", - "--destination=gcr.io/$PROJECT_ID/celo-monorepo:celotool-$COMMIT_SHA" - ] - id: Build celotool docker image - waitFor: ['-'] -timeout: 1000s \ No newline at end of file diff --git a/packages/celotool/genesis_baklava.json b/packages/celotool/genesis_baklava.json deleted file mode 100644 index 3d4dc7fdd..000000000 --- a/packages/celotool/genesis_baklava.json +++ /dev/null @@ -1,523 +0,0 @@ -{ - "config": { - "homesteadBlock": 0, - "eip150Block": 0, - "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "eip155Block": 0, - "eip158Block": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 0, - "petersburgBlock": 0, - "istanbulBlock": 0, - "chainId": 62320, - "istanbul": { - "policy": 2, - "blockperiod": 5, - "requesttimeout": 10000, - "epoch": 17280, - "lookbackwindow": 12 - } - }, - "timestamp": "0x5b843511", - "extraData": "0xecc833a7747eaa8327335e8e0c6b6d8aa3a38d0063591e43ce116ccf5c89753ef90f08f90276940cc59ed03b3e763c02d54d695ffe353055f1502d943f5084d3d4692cf19b0c98a9b22de614e49e147094ef0186b8eda17be7d1230eeb8389fa85e157e1fb94edddb60ef5e90fb09707246df193a55df3564c9d94d5e454462b3fd98b85640977d7a5c783ca16222894a4f1bad7996f346c3e90b90b60a1ca8b67b51e4b945b991cc1da0b6d54f8befa9de701d8bc85c92324946dfdaa51d146ecff3b97614ef05629ea83f4997e94d2b16050810600296c9580d947e9d919d0c332ed94fe144d67068737628effb701207b3eb30ef93c699482e64996b355625efeaad12120710706275b5b9a94241752a3f65890f4ac3eaec518ff94567954e7b5941bddeaf571d5da96ce6a127feb3cadadb531f43394f86345e9c9b39ab1cbe82d7ad35854f905b8b835945c3512b1697302c497b861cbfda158f8a3c5122c94a02a692d70fd9a5269397c044aebdf1085ba090f94ac91f591f12a8b6531be43e0ccf21cd5fa0e80b094718a8ac0943a6d3ffa3ec670086bfb03817ed54094b30980ce21679314e240de5cbf437c15ad459eb89499eca23623e59c795eceb0edb666eca9ec27233994c030e92d19229c3efd708cf4b85876543ee1a3f7945c98a3414cb6ff5c24d145f952cd19f5f1f56643941979b042ae2272197f0b74170b3a6f44c3cc5c0594db871070334b961804a15f3606fbb4fac7c7f93294c656c97b765d61e0fbcb1197dc1f3a91cc80c2a494ad95a2f518c197dc9b12ee6381d88bba11f2e0e5944d4b5bf033e4a7359146c9ddb13b1c821fe1d0d3949c64da169d71c57f85b3d7a17db27c1ce94fbde494b5f32e89ccad3d396f50da32e0a599e43ce87dd794ba40db8ab5325494c9e7e07a4c4720990a39305cf90b7cb860d5b174e904a2dfbcc181640651bc4c627c86fc9611d92795f18bfe779efb377ae799329419f4ee5a1e5c12103f9a5201257da7a821439d4c86731efe1959bf4076fccf1404c6bca78b6065a466571ef3428f9e203a8ccef519aad1622c9e7401b86078e6e671e6b9cf6f8fc21fb3f9eb8cf1d64bbdc1fd1213856c7fad711e9b26600f609a2e9cf6322f5cac415eaca793018b9fa902b49d0828258aed10b247e4409c320244adcfc941af6a09e87df18edd5239df5d12e4c38858f9159f5cabb680b860dea0e3506854e5d08b932c558da137c231185169d8490cebe070eee539eea00842a3a9787c79859ee82fec298bad0e012e8e4d859b9a13bbd7c97af622a1409276b01d51cb6e8cc36c8ff7a4d2492c35d9c258d37e8eb2cd59b9c9dcd7cc3e80b860dd794eab9568cea95207f500651867934d5c923bec817eb11536ac8ca4107b127d266ff9e67d407c10a82c4f529ac100080357a69ec30d5e7cf0c68109312b6137ca43cbe7ca4a58a7ff34d1d9c70be34fbf3dce59edd1248709091b80c8b580b86049ab79869c44658468d010f831680cf798bc9b7a26145be11b7f6ce547d1e7c13781548663cf710b1d9dfde04fa44700865048c711d0bf2715dc089ed9337e822fb8ce2b889e1512d1de58b17004548e246c14f0fa37988c9edc5cc8f895b400b860855b3dc7efe86a6907eb56a0ab2b663123e28f469359bdf558864b12a867b52e73acf0833534303236c350e2f3489101289db1d0d3f9a9ebe00e18b20109a91e012dda871a62cd513b85f42fbe5684c8131067402c7e944d27ad10c76458fa80b8601e8b9ec07ff41b4a7b9636470920c7dbc175ac79441f12b3f93da55c26a48c17367ac3421106c955b4913460c9558501410c7dca5cdcd9372a82fa22eed8b9b7c725e390fb97b3a354cafeae18b99b24e07609122ac17924ae40362c48ca3b80b86021eafc9e179b482c450eb092766e79c74bddc02126eb07a56954a74d9cae7bf9aabacd22178a4646fcb2e57ba8826d00c71802db142b2f9d62de6295a9c21835965e0ea5564f37e57241561341bb870723fc828f20100250af23f59f32fa3900b8603044b1df058de34a35bf47d35a83e346e961a4cb4426fb5ad0ea9fc4d7a2d1f74ca6aa9ff3218f41e23b2c097181a80150f3e56f6ad0aa9d57ec9e71b1538a22761cf430783b73c12c0aed2232318374fdc18347270c1f4ce0fb032a788c0f00b860796cdfcfcc45ac40ce1c476d419805d59bb3511aebfc8e2c5bfbeb757ae5005713994fa21ced588c3b73d4e469dd1201a41c53b85c2a16a0582b9c0e375dc35b92b4e3fd4fc8a8802337565b840a9537368e16c4c076deebef8e81d463c77101b86070534c36b6f06081d3e2228167b4d3f0cf8e235b63850f8b2cbff9ded8c6bb62abb424a9aabfed54ce07143c374b5800d80b39dd3fcce57961858fff9f306bd74dfc576c55a6f8710bd9f35db772a53331fe69cda78ce9ab3ad4c2d2e08a8981b86051360cc471b15b3d2b1c88d1ed8595cfd89d9b9fab605408ffd1a98b0af0bc1293cbc2fe360a4362ffea907ac22bac0067e3259fb5d4064cc4813ec9449297f7b924034e9631ddc91e088b467eeae97b6133fd275f5f5830a936ba81b2bc9681b860ae05dd90d739565eae5aca380bef7a2dd3a6bdeb429f2a514864e52d8e60c0a9bc2e022292167ae221adea3ed2d19b009d715d34e3d5924a2cbc11503439c0bbe669e097698cf49a91012640c95dd7a9c77d2e06311a08d338b9541726162000b860c71dde0acd7a9014a2b4fbc0eee9d56711fa9683b6dfc9469c34ff61d52ba49f983c2de743aae2fa2bf7520de5bb9800333d40b75108cb4208d42597b60600de1bd83b282bed596e36783821af3675fd6267b578eba2613f186a43264d410801b86059e868a7daeb24dae2a81a8a397c8b3b4c80b74dbc566c0e8813194c4a0a94850abbc5fb63b56c2c55ad2a65d8534900c9810ecffa3fe2e3b5b759c9716ee3dba16eff9a1785c8b2f1c637322e951a4cc752c31ac400d8222c8ba25c47557680b860f5e06a742ce9ee4408a75a38eeb5c06803a87b97709e43308e14fd6a027e048706a31c4ef62084c8758754f95b897801b316a4cb159f60880f69a806ba64cd243727d644d1b10b8890935c2d1d753321f10ea9543418aa7e2b324ff76ab1cc80b86042cf85912f3b0420d43bc42775d51e77693fcb33a862fbfba18a05d5a8da3cdf7c5f105ee2e3413a9bed07e502af44002e3f48bec159a159db5253ea243d37a2090ff6e9c6214632100f364df129732e57512161b3957cb6f84603afc4859701b860d6592adca17cd2958a84bc1ed35e04aa33abc6ab93de2d3f78cb9e48f3036885fab3282ab7318e4103a4c078659fd9008e4ccde2494eb493f9f851eb1e0d338e2124b393d9491ad2f17dd4f468fa2ab80a7c0c2c4142f6bbb8eb6b33efcf3d01b8609787a55f5dfa9539d1b0146177f6cd56e7ca3b58a63c36cfcff3b14a78b68d7a5096219162a55e84525080dd834fb000e4157ec4baa6e21c51161f3e8b4aa8f828edcc93e1d8c6fa9a6608d01880064f86c60014c38087a83d8d8acd54375000b860effce8fdc3099723aa7be8d75a6600d3aca652f52aed0191dcb6bfb02cc88b8993fb29627ae5459f8c7affe1349a92001acdc1745ab09d073001521a9ec27158c5bf242db7fdf5745de83e340d7dbe7a9940c207a3e32d27d6406cca25552e00b8604c61d0bf7d775a61a61a5ef721663de02d0b379a1b589fe62d05917f67962459f0f8854f91384ad02b4efeed68ab3301ac31ec73f5f7e4546f329dcfab7666acbcd5022a51b229b7a9fe979d486b83984659a6cddee2bc49317e56af54498781b860d21657eb1b8e3d38c32873ce326195ee957059968d8926ea219852700d9a884289cd45c5dff6baf2528cb20bb3dc2f00f53c8221eb6c8056b14da363a98e573e4eaf46bc84eed3468364aa24848951c1de38cbe9945e47995e23ce3455dd1880b860da25af7a34042ca2e366d359dede467837181b89c6bd8a4d68c47f15952808f7a8c625a524d604a02936b7467f2a6f016a6a9bdf109c3aa4d3c6f6314dc04ff64bc4297e85232b16071eda952b0cf2b297f9a6cbba24e9805c6ea440c04d3f80b860ced170a03c9d7e505d04e13307eed25e1af3b96317799088881154ab6891fb13ca05a4ddbf7a63c233957502c2ff67002ee5015e2083b498773be347939124008c2f7f856ced900701077b5c4c6a1622c08b0f69fbf7e2e97f92ca8f1c870901b860a4c7328ef48a970211572e76c1c3bb2b8a1440233774e12479125808290fbc0e57f276034fa2735f1550fdf7a1b56101c97845c23dba5023aa922c6152028bbc93f39f222b4c58a015db70094efde2f5567f03c7eda6355e8ef9ad9c43065c81b8603b07a92815d862c4be414d89f03c9f5354190954ed4c3dd0282e5964aef7954469dee36726340db09aadfba322354c016077b90479c8c5301b362f83b71d9c351ffb57ca39ef611ca4f5d6a8d614411e77a2fcab5de1e6adb9f1a6e3c5f77a80b860aa6f0e66fe03056fdd2a7a003e0b9f29133f2ebab7c26d3699500b6ac51248f1e3f747a3c3a5b2d11d817b1252679400291d023ae71f3a9f5723b122081a6932075a974f75467aef517944c8d206d307c4a5ebe8fc8aa374baf75dfbece96c00b86038e7f70fab621ef588c0fe24d9f288387913faaf52a5813f7da47d5fa8a9e32a098e6323ad2c1133221a43bd97b40c01d6cad22a6c7c2969beb123a42b41539c3a38da1b0ed7d762aa9ab67239a1d0afdfc3466287ca4ad33bb69b647f144600b860acde65212b2f8f1e15bba36f0b2cc0d345678718695e78c7bfbe1566c4691c0352237896e812217184cdc897bf96f500cf616132520278666d00d27a07610de649687cfc28f8c568dce232583004b21d0ab8ea4361d84eb6f9540a1d0b3c3800b860761f7d6dd8c2df51b358a60bd809c693a364b0aefcfa4cb492525ab82b9a3c506e1ba17347f82cff57411ddd6bfd9d01cf9bd337de5916008358cf6f1b411131f43818607db22f439ecb431ae773cea4d39b8c3057b35c64b40beedfdd9e6d8080b8410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f86480b86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080f86480b86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080", - "coinbase": "0x0000000000000000000000000000000000000000", - "alloc": { - "fCf982bb4015852e706100B14E21f947a5Bb718E": { - "balance": "200000000000000000000000000" - }, - "0xd71fea6b92d3f21f659152589223385a7329bb11": { - "balance": "1000000000000000000000" - }, - "0x1e477fc9b6a49a561343cd16b2c541930f5da7d2": { - "balance": "1000000000000000000000" - }, - "0x460b3f8d3c203363bb65b1a18d89d4ffb6b0c981": { - "balance": "1000000000000000000000" - }, - "0x3b522230c454ca9720665d66e6335a72327291e8": { - "balance": "1000000000000000000000" - }, - "0x0AFe167600a5542d10912f4A07DFc4EEe0769672": { - "balance": "1000000000000000000000" - }, - "0x412ebe7859e9aa71ff5ce4038596f6878c359c96": { - "balance": "1000000000000000000000" - }, - "0xbbfe73df8b346b3261b19ac91235888aba36d68c": { - "balance": "1000000000000000000000" - }, - "0x02b1d1bea682fcab4448c0820f5db409cce4f702": { - "balance": "1000000000000000000000" - }, - "0xe90f891710f625f18ecbf1e02efb4fd1ab236a10": { - "balance": "1000000000000000000000" - }, - "0x28c52c722df87ed11c5d7665e585e84aa93d7964": { - "balance": "1000000000000000000000" - }, - "0Cc59Ed03B3e763c02d54D695FFE353055f1502D": { - "balance": "103010030000000000000000000" - }, - "3F5084d3D4692cf19b0C98A9b22De614e49e1470": { - "balance": "10011000000000000000000" - }, - "EF0186B8eDA17BE7D1230eeB8389fA85e157E1fb": { - "balance": "10011000000000000000000" - }, - "edDdb60EF5E90Fb09707246DF193a55Df3564c9d": { - "balance": "10011000000000000000000" - }, - "d5e454462b3Fd98b85640977D7a5C783CA162228": { - "balance": "10011000000000000000000" - }, - "a4f1bad7996f346c3E90b90b60a1Ca8B67B51E4B": { - "balance": "10011000000000000000000" - }, - "5B991Cc1Da0b6D54F8befa9De701d8BC85C92324": { - "balance": "10011000000000000000000" - }, - "6dfdAa51D146eCff3B97614EF05629EA83F4997E": { - "balance": "10011000000000000000000" - }, - "D2b16050810600296c9580D947E9D919D0c332ed": { - "balance": "10011000000000000000000" - }, - "Fe144D67068737628efFb701207B3eB30eF93C69": { - "balance": "10011000000000000000000" - }, - "82E64996B355625efeAaD12120710706275b5b9A": { - "balance": "10011000000000000000000" - }, - "241752a3f65890F4AC3eAeC518fF94567954e7b5": { - "balance": "10011000000000000000000" - }, - "1bdDeaF571d5da96ce6a127fEb3CADaDB531f433": { - "balance": "10011000000000000000000" - }, - "F86345e9c9b39aB1cbE82d7aD35854f905B8B835": { - "balance": "10011000000000000000000" - }, - "5c3512b1697302c497B861CBfDA158f8a3c5122C": { - "balance": "10011000000000000000000" - }, - "a02A692d70Fd9A5269397C044aEBDf1085ba090f": { - "balance": "10011000000000000000000" - }, - "aC91f591F12a8B6531Be43E0ccF21cd5fA0E80b0": { - "balance": "10011000000000000000000" - }, - "718A8AC0943a6D3FFa3Ec670086bfB03817ed540": { - "balance": "10011000000000000000000" - }, - "b30980cE21679314E240DE5Cbf437C15ad459EB8": { - "balance": "10011000000000000000000" - }, - "99eCa23623E59C795EceB0edB666eca9eC272339": { - "balance": "10011000000000000000000" - }, - "c030e92d19229c3EfD708cf4B85876543ee1A3F7": { - "balance": "10011000000000000000000" - }, - "5c98A3414Cb6Ff5c24d145F952Cd19F5f1f56643": { - "balance": "10011000000000000000000" - }, - "1979b042Ae2272197f0b74170B3a6F44C3cC5c05": { - "balance": "10011000000000000000000" - }, - "Db871070334b961804A15f3606fBB4fAc7C7f932": { - "balance": "10011000000000000000000" - }, - "C656C97b765D61E0fbCb1197dC1F3a91CC80C2a4": { - "balance": "10011000000000000000000" - }, - "aD95a2f518c197dc9b12eE6381D88bba11F2E0E5": { - "balance": "10011000000000000000000" - }, - "4D4B5bF033E4A7359146C9ddb13B1C821FE1D0d3": { - "balance": "10011000000000000000000" - }, - "9C64dA169d71C57f85B3d7A17DB27C1ce94FBDE4": { - "balance": "10011000000000000000000" - }, - "B5f32e89ccaD3D396f50da32E0a599E43CE87dd7": { - "balance": "10011000000000000000000" - }, - "Ba40Db8ab5325494C9E7e07A4c4720990A39305c": { - "balance": "10011000000000000000000" - }, - "8B7852DA535df3D06D6ADc1906778afd9481588a": { - "balance": "10011000000000000000000" - }, - "a8F41EA062C22dAFFc61e47cF15fc898517b86B1": { - "balance": "10011000000000000000000" - }, - "66a3Fc7E8fd6932568cDB6610F5a67BeD9F5beF8": { - "balance": "10011000000000000000000" - }, - "10301d9389653497F62876f450332467E07eEe1F": { - "balance": "10011000000000000000000" - }, - "6c3ac5fcb13E8DCd908C405Ec6DAcF0EF575D8FC": { - "balance": "10011000000000000000000" - }, - "85226637919D3d47E1A37b3AF989E9aE1a1C4790": { - "balance": "10011000000000000000000" - }, - "43BCa16603c56cb681d1da3636B7a1A225598bfc": { - "balance": "10011000000000000000000" - }, - "E55d8Bc08025BDDF8Da02eEB54882d0586f90700": { - "balance": "10011000000000000000000" - }, - "40E1C73f6228a2c15e10aF2F3e890098b777ED15": { - "balance": "10011000000000000000000" - }, - "DbbF476089a186a406EA13a4c46813f4BccC3660": { - "balance": "10011000000000000000000" - }, - "7baCEA66a75dD974Ad549987768bF8d8908b4917": { - "balance": "10011000000000000000000" - }, - "fbF4C2362a9EB672BAC39A46AFd919B3c12Ce44c": { - "balance": "10011000000000000000000" - }, - "A8dB96136990be5B3d3bfe592e5A5a5223350A7A": { - "balance": "10011000000000000000000" - }, - "1Dd21ED691195EBA816d59B3De7Fab8b3470Ae4B": { - "balance": "10011000000000000000000" - }, - "058A778A6aeEfacc013afba92578A43e38cc012D": { - "balance": "10011000000000000000000" - }, - "13f52Ab66871880DC8F2179d705281a4cf6a15fB": { - "balance": "10011000000000000000000" - }, - "eD1Ed9a71E313d1BCe14aB998E0646F212230a33": { - "balance": "10011000000000000000000" - }, - "c563F264f98e34A409C6a085da7510De8B6FE90B": { - "balance": "10011000000000000000000" - }, - "c6D678fC6Cc1dA9D5eD1c0075cF7c679e7138e02": { - "balance": "10011000000000000000000" - }, - "5179fc80CaB9BB20d5405a50ec0Fb9a36c1B367a": { - "balance": "10011000000000000000000" - }, - "0d473f73AAf1C2bf7EBd2be7196C71dBa6C1724b": { - "balance": "100110000000000000000" - }, - "6958c5b7E3D94B041d0d76Cac2e09378d31201bd": { - "balance": "10011000000000000000000" - }, - "628d4A734d1a2647c67D254209e7B6471a11a5cb": { - "balance": "10011000000000000000000" - }, - "E1601e3172F0ef0100e363B639Bd44420B7E5490": { - "balance": "10011000000000000000000" - }, - "3337F2Cd103976F044b55D3E69aB06d1ebB142Db": { - "balance": "10011000000000000000000" - }, - "8D0D5c57dC232Be15Df4A1a048EF36162C853b94": { - "balance": "10011000000000000000000" - }, - "14800c28F3cF1Dd17AaC55263ef4e173b0e8e3Ef": { - "balance": "10011000000000000000000" - }, - "f3996A0f0f593BfD5E39780059C5430fab7359FD": { - "balance": "10011000000000000000000" - }, - "2217FeBe31Aea6C771AF163dCc453F9f060a4a00": { - "balance": "10011000000000000000000" - }, - "f426CC817400766cd6b44F13Cb63Ca648e323484": { - "balance": "10011000000000000000000" - }, - "B2C4913e257a34445Ec31685E625bb4060FB8e1f": { - "balance": "10011000000000000000000" - }, - "9438dbD05dfC19F049a469185c7599daa82646e8": { - "balance": "10011000000000000000000" - }, - "4BeD66Bf507f3CF524704267908Ea4ee3cDe3053": { - "balance": "10011000000000000000000" - }, - "9a850fe8105e9CCfBD9d1D06D535BB4948f3f6Cf": { - "balance": "10011000000000000000000" - }, - "1277eE554565542A8d0553E1e54006d006db75bd": { - "balance": "10011000000000000000000" - }, - "D7e829bE8E374D3fBbd2F68D9A916cB2f769BA89": { - "balance": "10011000000000000000000" - }, - "3691b847eD14E296afC90Ff3E37D21e518306170": { - "balance": "10011000000000000000000" - }, - "c4C703357B01672cF95bFa0450a5717812Bc7ffb": { - "balance": "10011000000000000000000" - }, - "0c9369077836353A8D92aeD29C72A7DfD300B354": { - "balance": "10011000000000000000000" - }, - "856DF2A3bdBb8086cE406C469dDE94d12C1E3176": { - "balance": "10011000000000000000000" - }, - "E40B3e5c59e2157037b699895329DBe4aA33C039": { - "balance": "10011000000000000000000" - }, - "edb47aF3aC2325735722450D1E7DA082bDDad58c": { - "balance": "10011000000000000000000" - }, - "315D669866E13fA302B76c85481F9181e06304Ce": { - "balance": "10011000000000000000000" - }, - "A5185E3328592428d5989422e0339247dD77e10D": { - "balance": "10011000000000000000000" - }, - "85Fd1d1Cd6655EbB89db7D6cA0a5C9c62F7a4CFf": { - "balance": "10011000000000000000000" - }, - "ACC9E4430EC1011673547395A191C6b152763EA4": { - "balance": "10011000000000000000000" - }, - "3824967C172D52128522dD257FE8f58C9099166B": { - "balance": "10011000000000000000000" - }, - "5542aDEA3092da5541250d70a3Db28Ad9BE7Cfc7": { - "balance": "10011000000000000000000" - }, - "c61Cd4477f0A98BfC97744481181730f7af7c14f": { - "balance": "10011000000000000000000" - }, - "5D7Ffd0fC6DAA67AbF7d48ae69f09dbe53d86983": { - "balance": "10011000000000000000000" - }, - "350914ABD4F095534823C1e8fA1cfD7EF79e7E4c": { - "balance": "10011000000000000000000" - }, - "ECa6f058B718E320c1D45f5D1fb07947367C3D4B": { - "balance": "10011000000000000000000" - }, - "9C577D0795Ed0cA88814d149c2DC61E8Fc48Ad81": { - "balance": "10011000000000000000000" - }, - "72fE8bC8E3Ff1e56543c9c1F9834D6dfC31BEDDC": { - "balance": "10011000000000000000000" - }, - "6Ff2CFa7899073CD029267fd821C9497811b5f7E": { - "balance": "10011000000000000000000" - }, - "4685D123aE928a7912646681ba32035ad6F010a6": { - "balance": "10011000000000000000000" - }, - "4799946c8B21fF5E58A225AeCB6F54ec17a94566": { - "balance": "10011000000000000000000" - }, - "1D7dA5a23a99Fc33e2e94d502E4Fdb564eA0B24C": { - "balance": "10011000000000000000000" - }, - "DFc9719cD9c7982e4A1FFB4B87cC3b861C40E367": { - "balance": "10011000000000000000000" - }, - "0c1F0457ce3e87f5eA8F2C3A007dfe963A6Ff9a7": { - "balance": "10011000000000000000000" - }, - "7dC23b30dFDc326B9a694c6f9723DC889fe16b7d": { - "balance": "10011000000000000000000" - }, - "3F0c4cFDD40D16B7C15878AcCdc91Be9ca4DeE79": { - "balance": "10011000000000000000000" - }, - "B984a83416F560437C7866e26CdDb94bDB821594": { - "balance": "10011000000000000000000" - }, - "138EA4C57F5b3984EFacd944b3b85dfDd5A78Dcc": { - "balance": "10011000000000000000000" - }, - "AD4f16F3435E849505C643714C9E5f40f73c4a5a": { - "balance": "10011000000000000000000" - }, - "6b38E861ec0b65fd288d96d5630711C576362152": { - "balance": "10011000000000000000000" - }, - "AE15D05100CE807d0aC93119f4ada8fa21441Fd2": { - "balance": "10011000000000000000000" - }, - "e0e25c5734bef8b2Add633eAa2518B207DAa0D66": { - "balance": "10011000000000000000000" - }, - "9039Ce107A9cD36Ed116958E50f8BDe090e2406f": { - "balance": "10011000000000000000000" - }, - "089bE2dD42096ebA1d94aad20228b75df2BeeBC7": { - "balance": "10011000000000000000000" - }, - "E3a79AEee437532313015892B52b65f52794F8a2": { - "balance": "10011000000000000000000" - }, - "Cc38EE244819649C9DaB02e268306cED09B20672": { - "balance": "10011000000000000000000" - }, - "eb0357140a1a0A6c1cB9c93Bf9354ef7365C97d9": { - "balance": "10011000000000000000000" - }, - "44370D6b2d010C9eBFa280b6C00010AC99a45660": { - "balance": "10011000000000000000000" - }, - "762438915209d038340C3Af9f8aAb8F93aDc8A9A": { - "balance": "10011000000000000000000" - }, - "9CBa7aD50fa366Ff6fC2CAe468929eC9AD23Ea2B": { - "balance": "10011000000000000000000" - }, - "4f4F159826b2B1eE903A811fCd86E450c9954396": { - "balance": "10011000000000000000000" - }, - "3C132B8465e2D172BB7bab6654D85E398ee7c8AD": { - "balance": "10011000000000000000000" - }, - "0582426C929B7e525c22201Bd4c143E45189C589": { - "balance": "10011000000000000000000" - }, - "fb542740B34dDC0ADE383F2907a1e1E175E0BF5a": { - "balance": "10011000000000000000000" - }, - "184Ca91AfE8F36bC5772b29cE2A76c90fCef34D0": { - "balance": "10011000000000000000000" - }, - "0C6f48B50B166ddcE52CEE051acCAfFB8ecB4976": { - "balance": "10011000000000000000000" - }, - "3aD2bE38fA3DFa7969E79B4053868FD1C368eAb2": { - "balance": "10011000000000000000000" - }, - "a6A690637b088E9A1A89c44c9dC5e14eD4825053": { - "balance": "10011000000000000000000" - }, - "C224B131Ea71e11E7DF38de3774AAAAe7E197BA4": { - "balance": "10011000000000000000000" - }, - "d3C18531f0879B9FB8Ed45830C4ce6b54dC57128": { - "balance": "10011000000000000000000" - }, - "02a272d17E1308beF21E783A93D1658f84F2D414": { - "balance": "10011000000000000000000" - }, - "57A1aC8167d94b899b32C38Ff9D2B2bD0e55C10d": { - "balance": "10011000000000000000000" - }, - "F8fc7D740929E5DD4eBA8fd5a6873Be6a4151087": { - "balance": "10011000000000000000000" - }, - "B2AfC45838b364240dE17D3143AA6096d3340A91": { - "balance": "10011000000000000000000" - }, - "eAf133d1e0Dd325721665B19f67C9b914EE2469F": { - "balance": "10011000000000000000000" - }, - "B7660F1B075e56780e7E026ff66995765f5f1f7F": { - "balance": "10011000000000000000000" - }, - "F25087E27B7a59003bb08d2cAc7A69E7c15a4be8": { - "balance": "10011000000000000000000" - }, - "E65054681206658A845140331459A057C4EB3CA7": { - "balance": "10011000000000000000000" - }, - "e7569A0F93E832a6633d133d23503B5175bEa5Db": { - "balance": "10011000000000000000000" - }, - "a9f6102BCf5351dFdC7fA0CA4Fa0A711e16605c3": { - "balance": "10011000000000000000000" - }, - "1AB9aA0E855DF953CF8d9cC166172799afD12a68": { - "balance": "10011000000000000000000" - }, - "6C04aA35c377E65658EC3600Cab5E8FFa95567D9": { - "balance": "10011000000000000000000" - }, - "6b82AD37e64c91c628305813B2DA82F18f8e2a2B": { - "balance": "10011000000000000000000" - }, - "AD5D1DeD72F0e70a0a5500B26b82B1A2e8A63471": { - "balance": "10011000000000000000000" - }, - "72B3589771Ec8e189a5d9Fe7a214e44085e89054": { - "balance": "10011000000000000000000" - }, - "74F57dA8be3E9AB4463DD70319A06Fb5E3168211": { - "balance": "10011000000000000000000" - }, - "b6f7F57b99DB21027875BEa3b8531d5925c346cE": { - "balance": "10011000000000000000000" - }, - "279d05241d33Dc422d5AEcAc0e089B7f50f879c3": { - "balance": "10011000000000000000000" - }, - "d57FEfe1B634ab451a6815Cd6769182EABA62779": { - "balance": "10011000000000000000000" - }, - "e86C8538Bdfb253E8D6cC29ee24A330905324849": { - "balance": "10011000000000000000000" - }, - "2C58D7f7f9CDF79CF3Cd5F4247761b93428A4E9e": { - "balance": "10011000000000000000000" - }, - "37326cEfAFB1676f7Af1CcDcCD37A846Ec64F19d": { - "balance": "10011000000000000000000" - }, - "f01DCf91d5f74BDB161F520e800c64F686Eb253F": { - "balance": "10011000000000000000000" - }, - "Ba85246bc2A4fdaC1cB2e3C68383Fe79A6466fd9": { - "balance": "10011000000000000000000" - }, - "4A76f81eA26381981a3B740975fb4F605989b585": { - "balance": "10011000000000000000000" - }, - "00ee7168618BaE4F4d2900D5063c62948c6F0566": { - "balance": "10011000000000000000000" - }, - "E1aD0B232B4262E4A279C91070417DAAF202623F": { - "balance": "10011000000000000000000" - }, - "f611173319b22080E0F02eE724781d85f4b39Ae6": { - "balance": "10011000000000000000000" - }, - "158659458dff3a9E5182cA0e8Ba08F53463FA5e7": { - "balance": "10011000000000000000000" - }, - "FEB11610ad367b0c994274A8153E50F4557e473F": { - "balance": "10011000000000000000000" - }, - "e1eB2279f45760Ab9D734782B1a0A8FD3d47D807": { - "balance": "10011000000000000000000" - }, - "8667d005eCF50Eb247890a11FCdCfC321DC1Da9f": { - "balance": "10011000000000000000000" - }, - "5Ce612A664C2f35558Dcab7edb999619e155CD07": { - "balance": "10011000000000000000000" - }, - "aD95f88cCd3aBC12ddd6cD0b9a777B95339b747b": { - "balance": "10011000000000000000000" - }, - "6E5a5A2963F6d0C2EA26682a152fE3ac7CBC1227": { - "balance": "10011000000000000000000" - }, - "000000000000000000000000000000000000ce10": { - "code": "0x60806040526004361061004a5760003560e01c806303386ba3146101e757806342404e0714610280578063bb913f41146102d7578063d29d44ee14610328578063f7e6af8014610379575b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050600081549050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610136576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f4e6f20496d706c656d656e746174696f6e20736574000000000000000000000081525060200191505060405180910390fd5b61013f816103d0565b6101b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b60405136810160405236600082376000803683855af43d604051818101604052816000823e82600081146101e3578282f35b8282fd5b61027e600480360360408110156101fd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561023a57600080fd5b82018360208201111561024c57600080fd5b8035906020019184600183028401116401000000008311171561026e57600080fd5b909192939192939050505061041b565b005b34801561028c57600080fd5b506102956105c1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156102e357600080fd5b50610326600480360360208110156102fa57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061060d565b005b34801561033457600080fd5b506103776004803603602081101561034b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506107bd565b005b34801561038557600080fd5b5061038e610871565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f915080821415801561041257506000801b8214155b92505050919050565b610423610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6104cc8361060d565b600060608473ffffffffffffffffffffffffffffffffffffffff168484604051808383808284378083019250505092505050600060405180830381855af49150503d8060008114610539576040519150601f19603f3d011682016040523d82523d6000602084013e61053e565b606091505b508092508193505050816105ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f696e697469616c697a6174696f6e2063616c6c6261636b206661696c6564000081525060200191505060405180910390fd5b5050505050565b600080600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050805491505090565b610615610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050610701826103d0565b610773576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b8181558173ffffffffffffffffffffffffffffffffffffffff167fab64f92ab780ecbf4f3866f57cee465ff36c89450dcce20237ca7a8d81fb7d1360405160405180910390a25050565b6107c5610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610865576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b61086e816108bd565b50565b600080600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b9050805491505090565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610960576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f6f776e65722063616e6e6f74206265203000000000000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b90508181558173ffffffffffffffffffffffffffffffffffffffff167f50146d0e3c60aa1d17a70635b05494f864e86144a2201275021014fbf08bafe260405160405180910390a2505056fea165627a7a72305820959a50d5df76f90bc1825042f47788ee27f1b4725f7ed5d37c5c05c0732ef44f0029", - "storage": { - "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x0Cc59Ed03B3e763c02d54D695FFE353055f1502D" - }, - "balance": "0" - } - }, - "number": "0x0", - "gasUsed": "0x0", - "mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000" -} diff --git a/packages/celotool/genesis_baklavastaging.json b/packages/celotool/genesis_baklavastaging.json deleted file mode 100644 index a0a350df7..000000000 --- a/packages/celotool/genesis_baklavastaging.json +++ /dev/null @@ -1,223 +0,0 @@ -{ - "config": { - "homesteadBlock": 0, - "eip150Block": 0, - "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "eip155Block": 0, - "eip158Block": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 0, - "petersburgBlock": 0, - "istanbulBlock": 0, - "chainId": 31420, - "istanbul": { - "policy": 2, - "blockperiod": 5, - "requesttimeout": 10000, - "epoch": 17280, - "lookbackwindow": 12 - } - }, - "timestamp": "0x5b843511", - "extraData": "0xecc833a7747eaa8327335e8e0c6b6d8aa3a38d0063591e43ce116ccf5c89753ef90a62f901a4944588abb84e1bbefc2bcf4b2296f785fb7ad9f28594a83dbbd6565fffa42e0439e08c97d253427ff86c940d8ccae442ef5e452e4948feffe0b8295073e51f94c955ad5b9292647669f7e6d544125e4632360eb094f77e9dd83a22cab28cf4cedad25792348249e8de94fffa11ef0475ba651a3bcb9ba42184fbcdb9e69e94c58ddc41e3af815d5c3c2d8a8465e0832e87005f948baaf7c944452b8873c70af106d129dcdad99eec946da12f24f14ad0efeea4fd0b1b14b2bf26009f17942379ad55e7d3175674efa7a02e1c30ca423de9b794a49557af4be0d55c1c1c419c3f3f0067fdc9f51c94a517e5ac9e2d409cb055f35f030c4598b28b3b769429974d953f6fdda44c9c90677426719e086a03fc94f9fd3859a9b3e0758328d7767c540c3397f28664944de1f59d382ae77048ce9ec9412f41af64e82016944cb3107cacf8272363cee5862724089f60f8c38694153ca761ba7316718ab80a0c019a545c9a71e332942a847599f069e3745a1fc5b6bd1cb4185151be999431ca13d06166304c4e227f016ebdd1a1a50e77269447de51228ec2650b4fe5dbcfeec208f68f332073f907a8b86031edb83bd19da2fd32959e52710d5a8177d7f3853fc6ab192cd0754ce84486cebbe0586c585a5a2255739aff3fce48009443dd17ee38ef23582b41560c70c088e37d686c5672146a93005563382c16644c6cab9d534ba200599cb9fce9390001b860deb530af5ca9bde08587ee01e0c92e9f62bc01c833a474b703a9dd957368e0fbf4585d6e3a849c34c4074c5ff6f27200e6df0c941f66650ff381a1c8b78d50d900de531199d999d8344e2f4423f9058bd42940aec18e789e3a23ba032901de00b860b6744672c6b69cb122321dc6b07d1c279a712db3e165901b6d89d28a1adc64076b3577c31d09879c55b69cb050e00a000a8f76604433c7ce68b1483cfa6b6ac198ae8b47986a140f6810b2f23d7c39ad6e18df8c4ef737f065d72cb350c17980b860454c4022c00a991579229ee764cfee95ed396bf92e366eab56366639237dcd06e0d73b687a89f96565849bb382d43f01e9949e065efbe9c433751cde2d720578973e4c73b3077495c24ed109c9554a2a8bef27ff1d35d501a32e5c3b95f10880b860c8129042c92534bbec19e52f4684991376925d7275e47c6c90b609b9cf732871526ce0773fbd29a71e51d9e9ca6c220027123bbbc9bb843936fd67a02a36b95ee83ced06e3f34bc608f1b81b44cc2f2a8131d2028e9df4715b3652ec43ef0800b860a69c450526807639775c4592cd439cc7fc628a9660dacce203fc3072bd524d7bf2e9f21ee7b67fd15ea53ba0a99921018e788c3dc7885e413e802eaddcd763527374b834cbd8650402daf798b0e1c258ab4784286fe41649776ab63200e1a981b8609de03d06d5f1d3222b67b0b65e7d9eec35685fa69e24f5c429e7ce1250efff812e9e19444f9c684cc524fbce7c851600f0ea65c91c3b2117f6828ca73e62134913571afc73d1743f3a79d067742cc9782138d5d95f45040cf2ed633a7d868581b8609c316c12d0f68667be982b2342340a051368a5cd199054efcb230263f8a1a3c0e7e6dc8d8c097a2e21bfe600022f7f01a85730c9cfab81f111020c0692a0e9f30afced6fe9dd377eff8aaec4af030d947325c5ddf8a7ef2c02769512e107c080b860d57d25ef5cacd7e3da9aff67523302ae423b8af7452129656ac13f1a8b2ae7dcb4a985655656ba0c20e0d21c83b7410065db6501fa38208540824459b71d8c1ed96b53b10d359b414a8e4b5f02558d3abebfdebc8fd30fcef252474a57e52781b86055601af6d309e6ca30c7b1c59bb0a2441ba1917f80851f0997dd79a35f90226734ff8268eb848d52000fa26fca006b014931f58eaf8f8af16faf7f196021bbfc014c21b01b27b95eb9a163b817261d4c2ceac14d37020889277f748122a60400b860af6427cad4bcc9b5c336abfdf14d34d1874506539cb5c492ad6210127783962e3729a5826c94d4aa2f81e74a6b824a00a211bb4e6a79db9adbcb334d00c87c9c838388b59d4aa3e2810acf23359451a0d5b9e6ac370b3dcbaf7c7b36e8fd9f01b86078e54d72c1f2494d4352a0b47ddeade7b88a8d959e691e480369c76cb244d7993d6917e6803b2e077c74ad54f2746a011246370f83a4283820de29f14c1c4fc3564d29615ea3f8317dd266a4555739575ee7428b30c27ef85aa68509d1946300b86054970d70b996b31c7fab533c7466fd606036c05515342407169f231b367c0f3456a11c26ff1d79edeb8fda0911be080127aa5a206f102a9fe1133ac5a875712a786983d81259a1ddb4e8161529c44b6599082a72aa2b0d713669bbacd5030b80b86032561cefa7f227f627fcea569a9332c4bfdf59653460abc712d7bf3a4b8dd087148564be38df63796346dfddfa49bb0008e8fada39f805891982ec250f33ccff7f7016b3bc86fab5b20c605c85860ac785707f186f91f36a3339d079ee440181b8607ec523dd6fcc98709acd8563035ddfca983e5faa725d90328ae7a4fafa8ba576ea5724a7f74ee056e4717d248527c3003c69b7f38d1250ced33dbbd74acadcfc0ffce6595982bcd47c97ea8f6a802ba581f8167a343e0e241a1950faa28f1d80b8606dda7632cc74de8c6071f78379c70dbfc9751ccf2e87c2fe1ccb101d513d220700c70f6ef2a4320aa95899f9b7f2530079b49ac64420c3da998cc76fc2a840b055da01b8e7894f5561b47c2e5f0de6b492e61bdaa3f602ddf1794a4f1509c400b860083290fafc9e80fa11523e24f7edbda1e55beda51c73892173c3221aeccb5b0755d926984ef2ed84e85a8ee33429a501853bd27b74be9da9f5951bc5b7e798c57470031fd6605a6688ec349e3fbf289aaea27482e7ef770ebbc924332d08f380b86062418bca58d3bac7c37dffb5b749ae7275710d697685f1310c4454295c15a424bf9eda516ffe39208d959db2b4121e01f16ef48dffc817443c8026a2d209ac9f1cfef13c25e7629485467fe4b44ae6e76ec074a51dbd0655404379087626be00b860076edd818b100cfa22cab56df2b15a7d37e36f8c3843e104f85027a253f5fa76a40c58f6698b92a395f09979146220010b5a9c5b96fac074eacf4bcb6265fe1d6c75a9d707307f81677cefec3fc5c6b0809c1da3126309e5cb33107525096b01b8600133959a8f45c1fbde384fa586e9208616795abe799c6d1c81bc99a380eb47cf3055652bb82b40639456d032b2af1c0065ece9eae2b2a18e3dd7ac32f9b2807b444a47b17512c5146545e37bf3259d08fec5ea57d46f8b177f7e0e61af7c848180b8410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f86480b86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080f86480b86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080", - "coinbase": "0x0000000000000000000000000000000000000000", - "alloc": { - "fCf982bb4015852e706100B14E21f947a5Bb718E": { - "balance": "200000000000000000000000000" - }, - "0d473f73AAf1C2bf7EBd2be7196C71dBa6C1724b": { - "balance": "1000000000000000000000" - }, - "8F7ca85A9E4A18B551b765706bd0B6f26927D86F": { - "balance": "1000000000000000000000" - }, - "3EaEe6C693420Ae86643EB2837978da8eEbf973f": { - "balance": "1000000000000000000000" - }, - "Dd3E5FcE22938c0f482004527D468a8799C4a61E": { - "balance": "1000000000000000000000" - }, - "Fb2Ee4Da251fC6A9DF7eb8d5c4ea1DeC99d127eA": { - "balance": "1000000000000000000000" - }, - "d321C7356DFB5b6F4AD9e5B58C51B46409fe1442": { - "balance": "1000000000000000000000" - }, - "bbbC38f6a383293522d4aEDaA98b7d2D73E90A73": { - "balance": "1000000000000000000000" - }, - "B9E0b0B8fdA1001392c8fFd19f6B7ad5286589F2": { - "balance": "1000000000000000000000" - }, - "44740e3eedfD3a2A2e7662de9165a6E20bBcC72C": { - "balance": "1000000000000000000000" - }, - "7a2cb0438e7B9801C29B39Ff94439aFf930CDf9F": { - "balance": "1000000000000000000000" - }, - "4588ABb84e1BBEFc2BcF4b2296F785fB7AD9F285": { - "balance": "103010030000000000000000000" - }, - "A83DBBd6565fFfa42e0439e08c97D253427Ff86c": { - "balance": "10011000000000000000000" - }, - "0d8ccaE442eF5e452E4948FEFfe0b8295073E51f": { - "balance": "10011000000000000000000" - }, - "C955AD5b9292647669F7e6d544125E4632360Eb0": { - "balance": "10011000000000000000000" - }, - "f77E9dd83a22CAb28Cf4cEDad25792348249E8de": { - "balance": "10011000000000000000000" - }, - "fFfA11Ef0475ba651A3Bcb9BA42184fbcDB9E69e": { - "balance": "10011000000000000000000" - }, - "C58Ddc41e3af815d5C3c2d8a8465e0832E87005F": { - "balance": "10011000000000000000000" - }, - "8BAaF7C944452B8873C70aF106d129DCdAd99eEC": { - "balance": "10011000000000000000000" - }, - "6dA12F24F14Ad0eFeEA4fd0b1b14B2BF26009f17": { - "balance": "10011000000000000000000" - }, - "2379AD55e7d3175674EFa7A02E1c30cA423De9B7": { - "balance": "10011000000000000000000" - }, - "a49557Af4BE0d55c1C1C419C3F3f0067fdc9F51c": { - "balance": "10011000000000000000000" - }, - "A517e5AC9e2d409CB055F35F030c4598B28B3B76": { - "balance": "10011000000000000000000" - }, - "29974D953F6fDDA44c9c90677426719E086a03FC": { - "balance": "10011000000000000000000" - }, - "F9FD3859a9B3E0758328D7767c540C3397F28664": { - "balance": "10011000000000000000000" - }, - "4dE1f59d382ae77048CE9ec9412f41AF64e82016": { - "balance": "10011000000000000000000" - }, - "4cb3107cAcf8272363CEE5862724089F60f8c386": { - "balance": "10011000000000000000000" - }, - "153cA761ba7316718ab80A0C019A545c9A71e332": { - "balance": "10011000000000000000000" - }, - "2A847599F069E3745A1fc5b6bD1cB4185151bE99": { - "balance": "10011000000000000000000" - }, - "31Ca13d06166304c4E227f016EbDd1a1a50e7726": { - "balance": "10011000000000000000000" - }, - "47DE51228ec2650b4Fe5DbCFEec208f68f332073": { - "balance": "10011000000000000000000" - }, - "8CC7a93e38b1DA573b41E48E5e47bA16E1273a47": { - "balance": "10011000000000000000000" - }, - "027c60c37Bada21d549a3B34B6B8e049f828e0AB": { - "balance": "10011000000000000000000" - }, - "363FCf294ABD4c8CdEa84175EcCDa950942921AC": { - "balance": "10011000000000000000000" - }, - "C233C86dCe075e78F0e36d0B84552495672A6948": { - "balance": "10011000000000000000000" - }, - "756b80b05A9CCE51bdFE91570e54CB09DEF9812e": { - "balance": "10011000000000000000000" - }, - "6b65877717370650aBA981b88A99e18b556F122D": { - "balance": "10011000000000000000000" - }, - "3C4f9eFd8700C223D3B7AE797FA78A522D961A7F": { - "balance": "10011000000000000000000" - }, - "30A8b35193818CcD401C14BcFA4FCd4d30bD4562": { - "balance": "10011000000000000000000" - }, - "7ce9B5FA976e0Eb4273a15FBc11aB3114396dBd5": { - "balance": "10011000000000000000000" - }, - "0cF60c0aa43cdcacfB50D589D9B1C2972094d4cf": { - "balance": "10011000000000000000000" - }, - "7b107F6A7E2342e1b36A14E34Ade428A62A0B305": { - "balance": "10011000000000000000000" - }, - "bF57d286f91b4ec3c0C7520e80FfeB40544d3b19": { - "balance": "10011000000000000000000" - }, - "8E4224DA8ecD76956695345a1addC671dE73f70b": { - "balance": "10011000000000000000000" - }, - "c0875151593247CbBEf78e9fd80Ffef102F8Ca8b": { - "balance": "10011000000000000000000" - }, - "37165522688De1Fc5D9CD17e836cad13570D60A9": { - "balance": "10011000000000000000000" - }, - "c8AD9F1A616Ea390318894770729572896319e92": { - "balance": "10011000000000000000000" - }, - "b531171f24f987644e3084251C2F2B22b25Df5aD": { - "balance": "10011000000000000000000" - }, - "c51aa01A1795e3DF7eF0e511bE2184397E659F8f": { - "balance": "10011000000000000000000" - }, - "B192511F6CFB728f90424f40145Db9d201e50591": { - "balance": "10011000000000000000000" - }, - "0E60b3040A367fcda85DBCC8eBC6589f188e4938": { - "balance": "10011000000000000000000" - }, - "2305daC99567d5810498C194Df27959ca4FE5bD6": { - "balance": "10011000000000000000000" - }, - "d410913B5c05e6eFd3FAb69D22B85301EEbC37b7": { - "balance": "10011000000000000000000" - }, - "4C1aE1e2120aAaC99331DfbBf4DcC0Eb1430b55D": { - "balance": "10011000000000000000000" - }, - "f72A61C0ebFE1b646452381967377eF6E5378012": { - "balance": "10011000000000000000000" - }, - "B932b6e0445011A5a2F572A64227FfD645B3A833": { - "balance": "10011000000000000000000" - }, - "2315C905Bc60AD5b3aF0d72eD203e1475C39E38D": { - "balance": "10011000000000000000000" - }, - "fF8dFf8f27ac481d9C66740eDAadE82734f392bc": { - "balance": "10011000000000000000000" - }, - "Ef72830EA68559fea1F22D46d02A4418D8444730": { - "balance": "10011000000000000000000" - }, - "7dB7a7e101C213ff24378f490c4BBD3F52575a0e": { - "balance": "10011000000000000000000" - }, - "e7843bdBd67EF741d41d4a0EBb14B36C1B8C6AbE": { - "balance": "10011000000000000000000" - }, - "0646451cAea32ba86E0Cf9509704ADE400c57AAA": { - "balance": "10011000000000000000000" - }, - "000000000000000000000000000000000000ce10": { - "code": "0x60806040526004361061004a5760003560e01c806303386ba3146101e757806342404e0714610280578063bb913f41146102d7578063d29d44ee14610328578063f7e6af8014610379575b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050600081549050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610136576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f4e6f20496d706c656d656e746174696f6e20736574000000000000000000000081525060200191505060405180910390fd5b61013f816103d0565b6101b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b60405136810160405236600082376000803683855af43d604051818101604052816000823e82600081146101e3578282f35b8282fd5b61027e600480360360408110156101fd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561023a57600080fd5b82018360208201111561024c57600080fd5b8035906020019184600183028401116401000000008311171561026e57600080fd5b909192939192939050505061041b565b005b34801561028c57600080fd5b506102956105c1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156102e357600080fd5b50610326600480360360208110156102fa57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061060d565b005b34801561033457600080fd5b506103776004803603602081101561034b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506107bd565b005b34801561038557600080fd5b5061038e610871565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f915080821415801561041257506000801b8214155b92505050919050565b610423610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6104cc8361060d565b600060608473ffffffffffffffffffffffffffffffffffffffff168484604051808383808284378083019250505092505050600060405180830381855af49150503d8060008114610539576040519150601f19603f3d011682016040523d82523d6000602084013e61053e565b606091505b508092508193505050816105ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f696e697469616c697a6174696f6e2063616c6c6261636b206661696c6564000081525060200191505060405180910390fd5b5050505050565b600080600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050805491505090565b610615610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050610701826103d0565b610773576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b8181558173ffffffffffffffffffffffffffffffffffffffff167fab64f92ab780ecbf4f3866f57cee465ff36c89450dcce20237ca7a8d81fb7d1360405160405180910390a25050565b6107c5610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610865576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b61086e816108bd565b50565b600080600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b9050805491505090565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610960576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f6f776e65722063616e6e6f74206265203000000000000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b90508181558173ffffffffffffffffffffffffffffffffffffffff167f50146d0e3c60aa1d17a70635b05494f864e86144a2201275021014fbf08bafe260405160405180910390a2505056fea165627a7a72305820959a50d5df76f90bc1825042f47788ee27f1b4725f7ed5d37c5c05c0732ef44f0029", - "storage": { - "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x4588ABb84e1BBEFc2BcF4b2296F785fB7AD9F285" - }, - "balance": "0" - } - }, - "number": "0x0", - "gasUsed": "0x0", - "mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000" -} diff --git a/packages/celotool/genesis_rc0.json b/packages/celotool/genesis_rc0.json deleted file mode 100644 index 393328964..000000000 --- a/packages/celotool/genesis_rc0.json +++ /dev/null @@ -1,87 +0,0 @@ -{ - "config": { - "homesteadBlock": 0, - "eip150Block": 0, - "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "eip155Block": 0, - "eip158Block": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 0, - "petersburgBlock": 0, - "chainId": 200312, - "istanbul": { - "policy": 2, - "blockperiod": 5, - "requesttimeout": 10000, - "epoch": 17280, - "lookbackwindow": 12 - } - }, - "nonce": "0x0", - "timestamp": "0x5b843511", - "gasLimit": "0x8000000", - "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000f91854f9041a9404aceda1f7909187796d6d59f842ed4aeea3e4b694d832461f6c870780263f9e8986b2cd1bb428290f941a13ab893ce00b72e8f146e2bb348e81d8e0910e945006b13983d03aac5b5ad95958cd6fd5d734bb2b94de7d3354eec658c6cbbe4a4b3f6aa6da63a121a8945c99cf35a86a2b495ec4dde1cca717ac341f945e9433753436f0586c77f8aa76d27a1486d8ec6047cf9413970bd076704cf24e7a88543ce0db073e3bbeb79493d94614c4cca93a97cdce21db5c674696e6dd74946ca0bf8bc24c5a0175a3ec133037814604f4fffd941354bc1df8844c82183646d4d6474a147b2a1be894e79bbc523556ba2bb457ade14d3394ba75d22cf194b589bb9df58e3fb545f094aaf07d2ec6a584abbc94e9efd6b2dcf46f4677f6e067869821a6717a7ad994c75404c5f4abea37b663a8ee5c1d76f3e35c4a1d9430ff181acfed6956e3b18a812f94849d98ff163594c72b2b51c72db728e8cf35b0e5c04938451a942294fc6092e4184014b8954612363052957fb38b695c943092bde74f475396a6c41dae1211dd26624a06e6941766e8a5d2ab98ead916bee43fabed08ce0c73dd94e8f113cccf0913b3bc69ae0e038194e285c6171c949669e3e907c90caafccbc668fe99c074c9e7ab6f94e1466d089588412920c3c3deb796ceb0c5235dc7944f7b30c72344c4270811a634a5bfe5cea1aa48fe946750196385695f6a693b40d689a18767590f5e2b949bcef1e207ffad55a35f19b6a0a8c282f16cb08a94b294662f6788a8b09f47bfe9f90fc87e52f0b9ca94ae49f41c0b5120149e5944703261ee8ccb86f58d9417c89224e78aba10546a0dc0563b73fc7056103994466bb2037f82eee8701f2f5013bfa9ad38fe421894bcf279d32fad69ba5169b3bc027ae7aac5e62c2094e03d02d1686b4e2d1bc09968825fe29458bf631f94b839fdde1578591000a2e5a77b50e3fa6f9bf7f394be480459079791fc3ed66d8e75892539d18426a59404e130dd50fc495210ff59d023c43c1d053d6e6d9475c12b971fef93f8a420b8724c60880a8806aed594c6782b9c3da0faacc7cd7fa5a0654485f3b7f5389493fbf71e611d10414707cc43b5bd8ab8380f3c0c94812b104f97fe0eb3db732a73f886ed809d7c9b7c94fede68be72688e4ceef312459d6922b549e91ce3943925e708970e83a33bbd60586c180e24f3d4abe3945a80e4c6703d70013f64521ff59c34f1ef2d548b94fbff194380133db49891da3aafa39f1e4ac3ed9494aa4fc38b65706138f3455a7dc93351bf9f852ec3946bca4159a155b9604ed05132ac0e95a36c9a6ee5944280119413a36456bdfa511fb1fdc9f659a53e55946bad169434301c27088c8fcc663715e2a2947582943a5e24148144b0b2c1fd8418c4dacc9e823303339410a6c36ba0c4b61fd05ce93da7b2b380a34ab5089445fb47864ba49e7e1c3eb9d4f5c9e4a39025d5d3f91324b8601471fa8b5ffbe112c6d894494a8f8f779e3bae02b3a2623924d0f98dd0e0445a64951bf59365a2aa542a10b2dc8e0c003c1d2b17bbe146ba12da2b7b4ce28d17bce7c5d099bd59b8b372159c3b156e0908f478f473762b0dc7c71146f8e74000b860fb11c8d67fd2634619b3ecf3feea2c616ecfc42bcd841f88191fa15d197399b00e193658de8a9bc7ed98e395a13a9b00bbd4a84341856a3e10f63f351992dce6cb7b8013a44a6309960ddde3b51782074d55a0401a81b3b6689b2224b3e60880b860ec18716b5a0b7db9f7d61481173fcf2e6b640fb13b6f06694552d471814e3386aee01af7e44c8e8c8b98999094f32e01c86646d21dcbf54b660bf5b16dd38a65e7a21d72f9c918b641da2a87c73a4630053177b2119f86f947895ff9ea000400b860abc62865f1b21c10040e53c048fcf1386b33ed914b1a1e229bc8b239ae1e1a7f645cf2a45ef2b1eb495545536a323701266d0d38a1ddc1251a83534d40ae9f5d370f813a127c288c1cb272da938e5af20795afb9322e30447add8e1ef30a5f80b8606904af78424d3d4743001d790d8a3a6f96c5464369f8d65005fb59eb840803208a7334720985eee63e8727417be2e50089e4d9076a8e4aafdee89461223cc4cd7b79ad4ee43f4eb5661ae335d95e90549a43c4b39f9497fd59f48ec426b99f01b860b8d5cb9651caa4533c9b4a91db9dc16f7e02bfdef77f73ec8fa36f64dc19e46858d6fa05d6270337e950f4b257499e00a6fefc966bfc28bd2109bc5f8830b5ad891bef81a000cc65259ccdad1fb850234de80da88e4e4870c7dadf85c5de5a80b860162afae7824ae865664766453ee3e595b2a2258715d9743ffcbeb21ceffa6b5df8b53c631c4da52d7a728df6739525001090659f2a58fa425334a594dd43cb3d7009814672cd2ff980eb5643e397477253f8e4d34aa413332efd1ce88cc34f80b86040970e807f3eb28288448dc5487f382dcb5750cb103cf2c71432cd3867dc022d75649880f29dc0dd2bc0fb675621ab0181a7d087faa9f1bbe85f47d3a890dd741c32bc3fc708a1b3af1e239309bd37ac8647a4c948eeacbb38512201b7df1301b860abec982653a35765ca6dbf813c5199922b2b97c5ab177829153902a24dfe2d34a89446357420111ebdb0fa794d550b00b4572f1e0197394cfd3857a4fd133e8e420b78d2e26d16506285fc87dde2f48c06033f03891fb10fc4dcece988c4be00b86037bd28a0bb83192056f1217be6991d3a2268cbd20f4a3b7da0d5c21a11ff9b67a4ded41e171c4075d15d35ac6f9cc4005040306c5385895114ae73a79d18860a078015a7695bd80751a0075c08013f45a78691146422875edb32701c5b330700b86062febf1d5e7b4372c973108e220c4010634afa3521996982e562379fe453a5dc068752889eea30339f1b7524cfbe140157ebcfa712313883ca59534ef17847ab394e0ba4ab412be660a1eeeccf7d32df80f25ee3bd23285bb278274f4f169880b8609a9a7809c80f53af392363b4ca8bae4ad5dbcaa79b8f742ac67cf1907c06ff3d99eee5298cce0f8658611d3aedccb7003528c49ef308b6d3079651751e27780ac6386dbf690fe01f085f18a59321d110cabe425786dbe7141cdd0ee79a70ad01b86032052e6f9f54800cca7ccaa3fcfb564ee577dc7f03a216c564d3fe4821f08aa2abb29ff5ed857ea36a9e1e54b2c64c00ce20ed5c771e38056e35502e1680d821e2d1aee6897365bd7bac665f7011b546dcad9231ac2fa2c83b2eef8b984df280b86042e5c9147aedbcae2c5e662fb3e74655f47cce7c8e4a3f64b97dbe6ed0089a375518f7547275952bc253797c35b74f01f25de8bfca9a0d7fa7d48f9ebe0f98f987383ab02c207ec5067275cd34dc4dad11e61d1c881c70da4135d656ccb52081b86051f56e8ff81ace6ca4da7374c60037f9773da298da52e9fa5a7d03865d33aca335d1ebc5540e92a9641f924d25be81018fc65ba8514e3270ce8215f89fc87978e8b31d50f62e2ad3455b964a72279fa7e816c64a4c713ed1a0979c4d60fe9901b86018d34f82f1e3eba03281b1ca3709989985a0e5ad36197326a251bf4325042bf01d8c479ca25fe29765b0d8de2813e600f2b30cf3672bf3effea745fd7f068b1361bc9b40f4e3f4a91f7f217fc248a8eb3fb1942e00e78ecfbe299c7918571e81b86062d109d216febdef5211998b27e9fb7fb4044b75cbbdaabc4acd4674e1b99e3ce94b1d8fedb163a208457512eccfa5008d1ac6b392dd6ac18062922af75cefa080e4624e847e843b1f9cac2833cd548890d50ecdd25532366ca51fc99afc8200b8601eb16de3bb6aaa2a1bd915e839996b9b542dca6e572aafdb40e33107418f878ab98ef93ab3356be7b3c3b56bcdb20d014247e669ff6c1123f66e4bf5ed7bf034eead1dcd600b0662ca786470cba77806b1a658fb08b345dcabc3de2579a49801b86061eee673d944148fdfced4a78fe3d68609ee58ffc63b4edeecbc9e19b0c204a1c7bdb54e7e1a8cc5b5b82f28799b2d00b1fdac61430b7f10f30dee9ac3c1467b3bdfcc3911c3a1edf461d5996dbc837e45f4b4221b893e52cb589f2f72460380b8601f464fd2676b15885a65d50fb35d79d3938ea43f7d27ac62d7b234c6aa671d0441cd5becef867d50573dddf7596599016da243a1b26115797b9a7ab7e7a5d0dd237053a2b23d1f6aa05f519ee298ca793221c3e08031fa844785626a35dde480b860ed753a819e47259cd8a0ca333f5c53260692bf438abfbda1e52518035bc72a33da1c99bd84655594dbb3b344b0506e00e8d60a2bdc2304ebcc704547c6ac230137ae4aaad2abeca9046879e434cb0cb28e80407d9c2c88b59bce0da2e53be100b86000380f86c503d051da502e5c881da7a25832215d239c66a55859353fc370fe8957f6975c99d98bf3a99bab5bcd560f01095308369e997f514c269665c70a7c3c24b50fe76e4dbe4d06368ef4eef5d100af992bffae5be31bb7391243a5d8a900b8603867d54f0eef3ea518e1eb47136caccc9fc6e2462846b8d516cda21618942708ea94022a7e7015111331883d79c35b00b58d519c4f5a2878230056b4079fb8d86756ba153128a9b6655dfa0eb511be3214ca5fdb2737efeb0c7cf4cad4e74400b860106f14f677bc4b406aba98e3c53db4f1af54d2136af68251e73368c3b232fa22b4a84f0a42d782a148190a8ec4569b00a942693b745a5969aaf23ba50eb30dfe302adbbdfc9b426e3480a60e254078665b8539db4be6ccda80b2fd8a37378081b86060f1356d4daa6a974a36c09da90b74a881acd8f2ad011b2501815cc05385f7f45f19a8ea9b69a61564295c00ca870601c8a2b2103b495088790c6930dd4050462546a5cd5c5d2f6eb96092584dc922a57530086a6190c131bb24cbeb012e1881b8605b07536bcbda46c75f5d9aa172fa987288e32678b4d61f02ce1045d7947fc38eeeac4512e827452491f8441f78ca8701881ff2fb683555a9b540853ef7f924d532ef045e49992ca1194d7a1a19fe01276e9981133b6a8e8df23d112bc411a181b86094384f0d1aabbb74f4142f4912ac6be043d9188e37d10780bc18ad18ecdf7adea9b6f92330d08a8b36a39f7e537e9300c6cbec405680fed4d3ac301b29bc29400309b39899011c1b950eec082c189f8be87e9790c7364d470654052cea20a780b86040e0cd46282a1f3475f347af631cc407b2b8b16c332e87024ad048b1289066506ace966a9185695bb72c485c020d62009ab316ec66e3773d6f63f425b9d54cde8ac0168d56eb18bcfd4b47527bcbf2d55a1df5012a27a2b59a7db07a760aff80b86012e57b96d7bbfa33f1b4cb066c962edf6e136b728b8e7ebbfa806165e93a1b45c534d00ec4344c70965340e87b459d00c9d54ca07c109d116ecd0422829cabc327ada8086085d7ca848cf615974f1d5b64041682fe1f913ec6fc7b1cd107a100b860beaa533350443f1a6f87987b29bcebf023ca1c9ba89b22d353b4abe7bce9a973190334ccfedb7d76767cbdcce9974701c64fbd05646fa4c28489f69c8fb27a84cf72c63f2b58c4eb0b15aecb6788c93da276f622c3c99ba5ce61a27da47b2a00b8603eb674128b8d4b487a5cda866e7e257768b516718528bfda6c444457fdf460deb230fd4b50718ed3d1d72b0094787c014a36b3662cad9b88469d774a5dfaf1f02b508adec452f60768ffccea4a389005f2abf2f5694ea932568d5fede4427200b860f46afe6d3b8ad94feb0fa9a20a4877d6b0ff82c2f9542d86957f32ec1399d2987c63dfe41b208200ff0c86e4722cf000ebddcc9700b46dde2b69eb52b9eb9307febdc8e830eb12725298aa686c5fa588d069d578e000d12a58f17fe5907d0a80b860acbdfb53273119e76ca26130ba32c66333d41aa0586ef415bde0b7cd2af2f298f37303836694d0983fb35d4a2dbcf600b0bdd4d5704c9055fb59684f537459dacbae8a5bb5fc8c1333cd612946c2f5195ebe9b19736ec1aa9c55c730b0935a01b86032a91a2907a2007d9160bdf16cecd0702f97e7ae4657cb1c2087c8da76eacc4c041916cb348e7f8e60b04794d3d21a019d8ad0d1819afd9161b0b33251e7c016f44cedc4fa3d76b4676bccc7533e3bfa213649383c5b3e2c6c83b31755752381b86088657485203bdb3490aac2df454f72e2c652abb570ffd28dadb5fa4772eaedd56f9af322b27fd92a815b90301fce210194cbd1030ada7556caec5e9fd4343eac25f6306d51e5176416f8dde221e319f43ea3c0bfbc7c9ada83b222f4448c8b01b8601ef3b3873a45e5ae5147333641c3d6892c445ee1a3c43fddea12b15dff203ad487e5d1800382aec4185cec0e2114c50098cbf0a1728b5c1ce87baccfff3e72bff2c51bd275e26ca9f624c313f02731b03725ba88fa8f3bb21c015f295b281200b86077c3557f788f31a6571ef0ab7492b4a50a27a70689c5eb9b60f01853ea6bc9edcb833a34eae060f5f90cae8501667800235c67723b1ec7002bcf1acb594b8d1c8df2f2654e7eed0cfd8cd979e1325386490552f107201d940011516090045500b86077aa64da8d4c5790e88381a5010e04f2b6833656b59656b7c82de481ba30dc4722e6cffa3f1f4279e1d2feb52c253f002ddcd8f12723f20c026800b1cd92fbc197fe526a6894f1f242b8d5db49a8328fd8219e1f5e9637df733f849826fcb680b860f10b21bf22dc2b49895224b0c3ebd135eb90dcc5754fce587de7a57825cb5317fc7ab79d6da70c5128bf92f0281d7901e7a08cf964bd241c348f5a2d9ee77dc4e52b1cd18ff2a9297442c7a39b31bce6da19cff512172cb64c96fecd41625a80b860b704769c2cad92f0935fe5591ce267ee42f7295e986ad5f9aacf521c3c424a18a8e3e14fc3f4a98c1d3ddaec5e3cee004302721b546f8ab1dfdb7164699717b126c2fdadffb64a5a30a545dea31a02a88dfebbc477a92dd5d7cc5c66b76f2480b860c2467f28f785cff88cf0b3c5243886def3409c2def841e905145a5717ea60994e3e7495220ba96a5f4f469850a9ef700b3a8f5a1747c57de8e88bfbbc839be7f2acaa40ba53858e2d37b35250829c6089ba1fef98fedf6e744325c90ea85e800b86055419af0800fecf25e6d92574bde4bf41168c7550ba600f156a9979f1af32b77f5b63368b39f92ca03ac1cc4d6b37d011240c13b007863c43076870e56117b9d4026b1268d7e5802ab1d28a492d974564de4bbea06d2c8db1c471286e9150d00b860336a9e16ae5745ad94a766ee1be7fc7ba3ce45dcdd78965cd238f2c63e5bf722052c8b436c7ce5512bee110e97677700323ada1620ab275f22938dc4a7ab2e07d14864524d84ba87db039ac19a18eafbabb287639f1177f4dda404bb566d4400b860a00fb9bd0eda3da5d11309fc2b7d2eb21533d6db0080c9ee4a75e3acf5c08e8e4e6565a3befc47729f0cee9c816b6200427720e0cba9b44bb20ff59752226c77941c70952bb02189e48a41b040c786d7d1f8cb69b8aa22ac42f3b8d2988f8381b860e88d29ab31574603fe9ac15e78924dbff6b48035208284e02099fa25e6d6e984dd3bf3148631a7544ff9582fbe204600e62b4fe24725064324b08c1773a900df6272fa5caab21947112b886fbcffed78cbe1e94c5caa28782cc2ae80c1c32c80b8607bc9faed4576390b7e26760c27746e8c1def4dd58e50ef1060434022f239aaf8f350f919d848dd313ab9c6497277360025ffcbc4e1f6a5346ddf9d940c0fd9da861759b998ceff0756cce7721801f31abb2487b5411d91fd440f5c0839b01100b8607e896229363f4e8f305b1ba8afbbc37d28d0295305fe4bd24fc74416e0bcbe9f2f21b8b67d190d4d0e1b158c1a705401f95347503220f265be2973511cd0da96e7070503c688f3ae20d932addcfd6156857473f083a195d38e4fff6031f6d700b86079e2e7d5d170514d1be612ed99c7f44c3b32e40faeb8b063e903439850aeb2563342223f1893fd71569f00a9fceb5d014310a61950969f89768a1219562119234173d6b1b48dada6e7385576c7ca501756179c22342eadfe25b57449812c7881b860c63e20aa60fb50e67f4759c812788e767b307b6e0fc9f04fc532bf59830d496f40e6ef4773b3a3158170ed2355e80c008feaa696564f896babd926d4eeff2625d20ddecd90caa1779e6f0316917733f5f3b4c89267b95a779e3bcd8e2b9d3b00b860c7c82587e95c7c13eafc5b30ae4986b1907dc586f0283309d15f23fe5b7d600a8dd8583cde4eaa82e1063293ee361b00ec9eb79f8e5e2e0fd84fd56cbd0bd472b9265217cc399d4f967f37e56880b4b1fed159ccc44fc52e7700bdfa0494310080b8410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f86480b86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080f86480b86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080", - "difficulty": "0x1", - "coinbase": "0x0000000000000000000000000000000000000000", - "alloc": { - "0x36940810BfDB329B31e38d3e97aFD673081B497C": { - "balance": "120000000000000000000000000" - }, - "0xfCf982bb4015852e706100B14E21f947a5Bb718E": { - "balance": "200000000000000000000000000" - }, - "0xbA8761304CEc7bE0f83C6F8Fa7EBBa3eE0b6Ae97": { - "balance": "27375005000000000000000000" - }, - "0xDb39DBE5abE42466F122b24c44518b1089ef8fC8": { - "balance": "57291662000000000000000000" - }, - "0x671D520ae3E89Ea5383A5d7162bCed79FD25CdEe": { - "balance": "20000000000000000000000000" - }, - "0x868E39ef6c51b979526c15Fb801a7dD567CBCffF": { - "balance": "20000000000000000000000000" - }, - "0x4eC7a9e67FB05f555d775604cF591Ccb3C47d7b9": { - "balance": "20000000000000000000000000" - }, - "0xaB5FD29Ce411C7b5c0c41d04a11d40f8fbCdA7a2": { - "balance": "20000000000000000000000000" - }, - "0x14F40ca7600B5605D9fE704A949DA41806509497": { - "balance": "19053338000000000000000000" - }, - "0x469be98FE71AFf8F6e7f64F9b732e28A03596B5C": { - "balance": "20000000000000000000000" - }, - "0x1cd43c11CaEaf4a43413258eF7E0704e157F7811": { - "balance": "22000000000000000000000000" - }, - "0x9268f359CAD800a2746FBC96C4A5CF68eE1c4EC2": { - "balance": "22000000000000000000000000" - }, - "0x10E0833be035607feEA41d32b6567D15D12511Ec": { - "balance": "22250000000000000000000000" - }, - "0x8f55CE88b4F62F22c663f5A539414dcCeF969c32": { - "balance": "11000000000000000000000000" - }, - "0xF607d4dd519B4bc963C9c48E8650E67C51DbC35b": { - "balance": "11000000000000000000000000" - }, - "0x515033209a0A29034DC3F037cC72a6014b902341": { - "balance": "10000000000000000000000000" - }, - "000000000000000000000000000000000000ce10": { - "code": "0x60806040526004361061004a5760003560e01c806303386ba3146101e757806342404e0714610280578063bb913f41146102d7578063d29d44ee14610328578063f7e6af8014610379575b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050600081549050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610136576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f4e6f20496d706c656d656e746174696f6e20736574000000000000000000000081525060200191505060405180910390fd5b61013f816103d0565b6101b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b60405136810160405236600082376000803683855af43d604051818101604052816000823e82600081146101e3578282f35b8282fd5b61027e600480360360408110156101fd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561023a57600080fd5b82018360208201111561024c57600080fd5b8035906020019184600183028401116401000000008311171561026e57600080fd5b909192939192939050505061041b565b005b34801561028c57600080fd5b506102956105c1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156102e357600080fd5b50610326600480360360208110156102fa57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061060d565b005b34801561033457600080fd5b506103776004803603602081101561034b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506107bd565b005b34801561038557600080fd5b5061038e610871565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f915080821415801561041257506000801b8214155b92505050919050565b610423610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6104cc8361060d565b600060608473ffffffffffffffffffffffffffffffffffffffff168484604051808383808284378083019250505092505050600060405180830381855af49150503d8060008114610539576040519150601f19603f3d011682016040523d82523d6000602084013e61053e565b606091505b508092508193505050816105ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f696e697469616c697a6174696f6e2063616c6c6261636b206661696c6564000081525060200191505060405180910390fd5b5050505050565b600080600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050805491505090565b610615610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050610701826103d0565b610773576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b8181558173ffffffffffffffffffffffffffffffffffffffff167fab64f92ab780ecbf4f3866f57cee465ff36c89450dcce20237ca7a8d81fb7d1360405160405180910390a25050565b6107c5610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610865576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b61086e816108bd565b50565b600080600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b9050805491505090565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610960576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f6f776e65722063616e6e6f74206265203000000000000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b90508181558173ffffffffffffffffffffffffffffffffffffffff167f50146d0e3c60aa1d17a70635b05494f864e86144a2201275021014fbf08bafe260405160405180910390a2505056fea165627a7a723058206808dd43e7d765afca53fe439122bc5eac16d708ce7d463451be5042426f101f0029", - "storage": { - "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x469be98FE71AFf8F6e7f64F9b732e28A03596B5C" - }, - "balance": "0" - } - }, - "number": "0x0", - "gasUsed": "0x0", - "mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000" -} diff --git a/packages/celotool/genesis_rc1.json b/packages/celotool/genesis_rc1.json deleted file mode 100644 index 7cdd781b3..000000000 --- a/packages/celotool/genesis_rc1.json +++ /dev/null @@ -1,133 +0,0 @@ -{ - "config": { - "homesteadBlock": 0, - "eip150Block": 0, - "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "eip155Block": 0, - "eip158Block": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 0, - "petersburgBlock": 0, - "istanbulBlock": 0, - "chainId": 42220, - "istanbul": { - "policy": 2, - "blockperiod": 5, - "requesttimeout": 3000, - "epoch": 17280, - "lookbackwindow": 12 - } - }, - "nonce": "0x0", - "timestamp": "0x5ea06a00", - "gasLimit": "0x1312d00", - "extraData": "0xecc833a7747eaa8327335e8e0c6b6d8aa3a38d0063591e43ce116ccf5c89753ef91f4df905559427f326ab753d62cdb55018c62e9ee7e671bbb121947eec94733d16b96c6fe877464630bb5be1e5c3f294f0d17b624521c0a599b063d73a73f9719307b48f94a7681958b7f07f4fb8bd5b0e075fb2aa2b021d5994ecc20b5f3d6cdf41fc12707ad7872ff64256e29794e5617da4dfa6ce4912f1d39889fe2dec2f7e66b39439ec4f2a82f9f0f39929415c65db9ea5df54e41d94341dec14b7a56c242ce9cf939815ec7bb11042449469901924e6c045a03cc163c6b8ae8af80fa1ee80940a6641d4736767d1f2bcf2450200ef384391b4419466bdb4d2ff2ee4c68517e6fcd25cc3034c86916094606311948f7426ddfd23c1521b15eddb52e83b29944cb90ebba92141ed3021f5dc4e6c8bb642095846948c6f9aad8281a21e7f6522602f2d6469c950e0bb942a1bff2452aca1ca5ffabbd34b2744109d11e4f594b4fa2d21b238e12ee4a863517cb5092f2330cb1b9442d441b6793e6162b979fbf6ad0af0063cbec96a94436d12f639a32509685080161ff0365fc15545f094e0c5f6172673ad70a76ff264cbc0df783930b47d9421245b0a2c3235f1108d1aa01ae376849d36e68494f27bb4eabc4400a1abe9d80d7537ab0ef1b058bf948440e805b89f48c932265e3c4ad033813669d87a942eb79345089ca6f703f3b3c4235315cbeaad6d3c943aa1fa695aa89958ebdb5346d6760b72250dc1d794173c75c8f1be201ce89cf426fe12c9997d7096269474288dbefa3a55986c039953b67139a466474fc49482f0e7879314516952f7961b15c63fc6b2734dfb9459f7b67e6beae0223ddc91eec010b670c553e8e094e10a8cc6c22cdc320c67bd600a1d8a0a46d7f40094e3020350aceea29b783e0c947ae001692b8f624894b952930a3656a9cbab21df5919f94c61a495bf79942289a63b4b4700eeeca35323ea51785f366dd705940223e40d1f93a6fe5bef63605992ada10740e13b940610b8b4e6f5c3241d53ed3374ddca8969cd053c9463b4b616c5345e3dcc9e21db69297e2129447f4e94c9a7781729f95b88239c3bfc91fb52f92b44a1169456259f876eb6a7264d9f1a59952baad599ff964094f139e74adec329e715ab49a68c5548a00e40cbc29433657019d60a0a41f1b9970bd4b28a3a83dbeafc940f5640bd556b0be19262d1817b213ddb3424d91d94ed8bf82d2e579ff6363aef139f8b147a0105f17e94d8c68ebecb6f074ac5c4fb66a690ac0ad38a5a3c94c6f916ad6e360651bb95f8e67c1c28805745d084943ed95d6d4ce36ea7b349cd401e324316d956331a944a03c4c2e101ac4612d89b79f61c9c5bdd51929d94dd0f3f7beb37fe9d4496f8098446b65ddfb1fa0294642cbe89a58909ba712dd11ed4c4b2359bd8c85d94ffbcf262c1d5c4392ef469ba79f2cd195d2affda9468e0104fd2b5a2c93e97c2ba172c4d2a4223f76f945cab520442de9babc290b25e5e2e6a1194ec670794bc6963fc0e2f5547ba949ed39e80b8388321104f9443882141555003b3e71110f567373b59ac4cb0bd9448cedc58b10af13d688631bc3cb78a05b8a6e56a9465698c9ec5af10345cd1e39472d60fb6133bad6f94d507309fd69635aa37810a65a4da27ec47a1ba0594c46dc0741ff61af883e284daea062ae7382e709194198958f0b860ab0e3937f468fe366aac9eebad2e940ec5a403212d732d8d7ced050e9510f6327453c694464cce7999b3d90a8f1ffaf94a71fbdea1e6543594097095b8cf5cabf0c39e548d8df55dd635d84d0794aa937da037e617e868795eac1dcd43c663014d3294f11073eb2d259b90a91954cae30d0e6e9ecc7f11945b55452bdba5971d606f47647bd383f3c3fa728594439d5e4d7578ecc9efa52a8cf1887b11fd0fb9009492f628b0157d47c992f5c69dbbd038b110e27826f918e2b86005f784c52234d0c40ab13b0636c5728217a8f3100046593c30271d39d59fcdb9a0053a874710e9c65e0d8a030c16a700b4ec430207cc5037c5e2698ef839fa0b7a4372f4b5217deda2a8df087e3b552f300016ce9147a2ff4db4c8a87d77b080b860d3f640c3da685893c41eb6301fdde2920c5a09296438abe5894074592f27547fb4ad02d222b1a330ff5aea065eff5200973d4fcb57808d8d9b09337e09aec279dc3337e758c51a3219596699006ee3683ff0c733f16eb917fad37f7f5d505201b86057b5158540d1672de49073e469e5426766094ce6514ac29580803ff9d22cdef3b6fed28a8ad9de63bf938c1c7b0e7a0156fb03f5363d09bf337713d8d45475df48ccea0fa793f591fbb62673545fc846c04e6aa9e2eaaab72c3b9ba4069ea280b860ca75a4c4e1f2898c0ae0ed53698b0271d1f8869ecd945891ae6a9b02682335af625c29f80572b440f91a3a343f3ea600a49a426960b6c1c5dd7b24540ecb745329312dfdd525fd173418c846f0096acba466a27446114f3a2b2a887986846b01b860b3dff5505fe9ec48fa11a67dbf166e7d5ab3473ff9f5fdc90c690eb1142ad687b17eb8ab0c08615c9397b351c53e79016d593d588f8c607b2d1136713d05066ffd8a30589357afa54a0a7ac8777372787261dde126c4f0c04bf741f809c3be80b860451da71ff5b1e9b4fd587fd76f53808191096cc5869596eda8f3ad697426a98a659f5f4818e57866d4b0dd90f0684900742a167b314f0276e5e6a8bc6f40ce1cd1d35c7f9be56f1240de596b30a4b40010dfd21b7fc9aef400faaa421e27a080b860277d5eedd8cf7d549296a6f8ad2869ec6e90183b9e8ebbf49a9d3ecd817757b50c6acc6cab9f0dbcf4b87251b6e82a0192a00c1e509225ec1ec08dcbeb04ba2808b16f72af90f33277e614dc19383256b3980421441ce3e75356ee35e5f62d80b86007431d3192f7a273382b645bc300cb0161c2395c005bf389698ce4a3ac56cffb9405456102f5b6e41b42bb28e7cb1f0141d3e1be1b066a94cc2befe88b0f5eef63c60a1ab8a1f0cc02e73c0ce5aac464332d3a2c1074a5126807a75323280301b8600d39e1cd00ff4ce5e41fa9ea90526f3e3540b64ba52954e5682f31ec20360b2995d5caac7cee778ff7c13aaca74b9b004032f87a331867e9ebc7ed06c5b77707c88614714f2e0ed30c85c519aa823aa9d1a7a56766a294c7802aad300b408280b860ce9efb226a3c085071c7aea84f66040dc16a1600893eb1e6ef507fa72c6684f24d2c3b4ffee9881142fc41cfbd6b3b01933838ed7bd05c16450cab703b12ee623f8745f7f618981601a9c4de1337fe881975bc8572536281b9dcc51400177680b860075724b0f2fa9ced3440a76107a53b02a0b8b5a5a510d94b02b5c0696db96910204d54ee3138b3e5949464585d98de00a2964d480ca31adf09c962802895ea160d195bce583e59094bf7c11d33eaffef12cb999284bcf842bbab2c87647d8801b8603b0ffa0a101f959879b7e14d830862981d6c311ffd440f214eee0a2891743a25355e9230266aeadbd20f3bde0ccb30008bf326df8fba9b701d4764ad49663da19417132edf4281df4560715649491d9794dc64e9540d16b51b362e139c3aa701b8601a65e75f0f47d7c92da92de15372a0052338b952cc1307d5ee1596a670fedeb3b5ac8bc690f3f5e5f34fb8d18a5441011d6023e3c2b343bffc655972102a7181dffcab47bd0a2d6d46eedc6f2b70cd64025715de2b8ae23c032e61b380663c80b86071ca0f2be942a733074e8e0d92ae0adc2617bcfe503b97f8339c8f1c498d85608fa5966da7abdd9651c9ce4e3411e900c4d65d5c7d858f1e5ee212c9e543d3727aeaa9abbdcb68848e7c990c06aa70a4bf2585959943935549e7a9e2c2ba0d80b8600122d3f6ae5e2bc6fdee3cd35a3522ea519bfa6f365451fa275c4688bcfb5cec418fa053a8859981e973ea273ca68f014e840d0ccf18cc7c498742103c3116732ef197a9f90f50bf64f83754a86ad441fe9691bfdf384a1aaacf38430a2b1001b8601135b86a2587c75c55db8274e498bd3f2887a1a455a665b8314655124c5e8197d3ef892f3dea2bd80b047530f837ae00dc263da929f0135a4f8ee73d47d5c2ffcaaa7b1e3a9cc59e496feeea2323e5eb16c9de2e3b973c35c0a82ca587477201b860e162bf706b79405326d52e29e2ea247a55ebf69ac34900e4e1249c3fe28fd3dabf40d7022f57bc7b16bedbc78bb49000ba7cd92e123b69309a0572cf49b1bdf4c5525ba656decffa5da91ed4fb565d384979e9a58f72986b654908bcc7308580b860e9dbc5c1d073954ad6ace9afb19d8679e8c87fd12cd1356999a8e167390f3de966f3485b500c40c61f829e12f56512001b4d4c4fcb19737735eba15d24d43231ce64cf348de3765fdbd01f4612af6ad7ebf9fafb594ade18a7717c189e9c2080b860bd8e3d6ad24e5a7e4f084b3142c6bebe26d248e09363a9bbfc9cd07ed59a65bc140a39564f6ecdf287c2ee1ed57a930035a92306b6d5925af8785c813bad6113ba42da88d3c0586e438df75bee506bdf9f10c927493524897ba485946f976f00b86030feb59a6804a2df697b3a40c691f176575ffb0d09fa167a59642d041dfec97e97414ea7abc8bc7bdad5f1a684e2bc00fb2c01bc03aa9e8caaaa82ca3210de31f9c7abff6baba5e08e2dbdfa85953ac39bf3b895627e7be493fbb6e346061400b860f24f6f1e6423fd83d1ef275484a5950fed90794d7bfb6224de768bf716646dee263de0d9ed4c681c0def78d16df0f000f1e17b8657f1d8e30dcb7e94cd1c79b9c82d8f04252b078ccf3719c7658dd82b9d93e02671925b5aeb4ae38163129100b860f6a586f1ceb85a23980bdfea738678f5906de5303a7ff6ceb3ad675f93a84fcc502275fd7bd8fde4de89fd381cb8eb000b3d496e248208d00eae4f421ce041d73789e794a372ca788655eb5413c3b7cab1c993e47ff6c568ca4da484bac88b80b86086ab977d6064531b136aba2fbcc50cfb332b939e0af22c7ff3800c804b33aad998ef69a97204076028a6946d627d2f0086992cba351fd538a91986253884325aba6d66ec1ac10eb8e18330180820cc388c22de7d64f9f0592b74ee5b35745a80b860fda02a60f25f87c0fc86be0bf52bf1d0be37db80661a2fa35c7f52a4c5f5edccca04768c762caaa2303f8cac2ba93e016dce7c8382e3d002e751e0bf33563eb8f6e7937ab2998300e96f5ed3d857d081ff389c495febaabe836a7cd06012ae80b8609271a103e5971edd694b3c6363a2517b0676849b05660094baf240ea9677e171169a8eebed5ad6000871b4f42d4ca701b74b10f91c0de059d225ced0222e391cf7bdb5934d1677193837d5a1f17bb710f4747956d819db51c817cbba53324b81b860719b2de30cbcdee6e62445b7c2eedb63520beb4cb6e4a55f7e121a5bc6a1143e1322d3ffea28ab624d30f6da8962b8003eeb056df8e46a49035c0aaf139a372e954d8ebc3cbd2d0b2e5727d54f3f4fcd0e95dc29bfa9f9ddcda98bbe8107ae00b860b054d545899f55cbb84853125d50ed06211ace3eeb6160a85583de508569e65592f5a221a000cb99997c0dd2738527010f2b1e83eeb7ca41c40ad9295b35f1172004a63567f140c1d2b0e04338161e8f1be88c1543ac75d587e42c3ed7dc1880b860e8de954d3100b125b2a3c1e4a81e3ac5f4b38f85c2ed91d752c507d4a37c338ca215e474a48511c599407b85c01d37012cd5012c74c5c0c3f88b4480a73bb52d1ff49848ca014f54cde1a891e6efa483b5f64016a9303515806c45d9f79a7e81b860bfce6153e2c2dabc724d9ccf5cad8916753dce1a495a29053ff7e5b74b0eace4889d5fd2d5859400d82b6bf29cecc9006b6e37152cb1f4f72e7d0c0897439f4ef886e26b4345d2f3e73bcf08d47f02c02976730620d7f844313c099894176980b860d56a6034613c0db14cad99e0d2dc3a2482ff8167a032218ac10508bb04fb8ef91d40a6ef0731f1e162761f09be237800363199f518a1bad98f9f2d179d2028137f9a86588c5cd91534a53d4edcc718b40aab61343571636d052eb7b288578c80b86025138a99de6619b2ad03707f847ac0f5d79b0fba2c67a02f5430a57c7a651d6cd63988cb91aa331acd8b7221a41fc4007be73ad86365de5029c22186d2c90a864fd3d386cc074b25f33b4e5f17839d2780b62390f1fe63ec690c1022c039f500b860c1e12e9c0b26d73c27dd5f60f08aa15c952afaa395dbc8b4cb99453bbf3f14ede8a9fc579f64500497344cb3637aa900ac8618d237580558d9ab5b042ac411fd121713744378c9f4d897907f09a71af9331bfecb3853e3f0577be558c9019881b860c8e6cf45b640fa91385b4f7e891fe68e5ef6847d032d6ee1b52eef0ff577ad796b881537f94adcbd1b52ba3e0e5d7e014e97406029095598a373fd6d9b6c7754aa87b87560e363faee89c11482cae4a063d7cbe65747f2b095cd2f6688a8bd00b86008fb22b9fe04caf62059216dfa1d2274ade1df9e8dc0b3c37c2f04a8b3d30a73f8b7ddd873d08c9b9302b936d303380147ce0e19c4600b780a1814730462147fb8280fbd7fe0aa7290d325a2b7b5092e05c037664a0aaea127b0d95fd13e3d81b86068dd5abe43baf4f4817a49b094c0bb19ed4971c49a6f91863163f655b6f312d80b7c7843b4cb7a27f7e54d48c41c7a01c5e22e1b0e38a5dbb03dfee76076a9af56146359add6003410005332417f6b65db718acce693cfa21a8fd92f6ad72800b86091785b64cfd3ac6025b6b536499ac63868344b8f86660ed73b574b000477807d53dacf1d9da258ee1b113485a01579001c5a510dd3b3c5ff1f417c4d97faf997aecedf7602bd96155f8396f5c9fa53d2c601b0de0241fff49939b8a97ce59f81b86000d869e78871139e8a5ff6d590593d94ea39ea73e87ac8d901f0f524372b93752a488b34e05afe05ab53b1c1b5b9a50040341dc01361110551358c9e982f30755e19ec2ad1c1a40afba9998f763599149b976caaded14c1793fe8c469b17c900b860e87f2bfc49c076239d7522280098c9c4808524c67f3891608c42a510340d64c7e3c1c074c34050007837c13536ee4001108efc87fb2eb8c3236a738122ec086a7b8e6857e82454ff6284a81bf0362424ba96be762d4c06e6aa1b59f20c870780b8608bd2cb218f465c82702aba73a061227cd83dd8e3115ae592811a4d9a8236e3cb99cfe81b2e22e3620635d42f63b7db00cd546bdf9fad7b49d0b4686962c8e0f4544c8df9f41d30d7d489c86745ef9b61a7dfb498f7554eeaf7e24654e5b2e080b8602a5d5145b7a8100575e96cadf2513e7e64dc1354bd891a24f985c2574c9f5f136c6837eab290543d769227785520970133022637837b6e711918f3d2e98291bf3b518247b54e925a0cd080d517731b2725be888fca298ae9ec6f5d2c19146b01b8609cedde7d49e2e115896b789ece09a4e8816fae153de891774f0f716a3088e01754498f8ab82d3a4ef5d53dbe17338f0089d1de1eb60bfe3ec2b9701cd882b1c174bdcfaac2225f57481676bd3ee845825be823b9f9317e407b015159b9ce7e80b8609124b91b223bf9bcb33f75ab8fad0180fdc57536d34349945b80458abc8e59cb06005fabea656b2cd0dc74c0d06160019706965ec3ee0d3b9dd76eb9d39158bd512fe7384bb9e139bc6391d5f7b969397bd85a91bb91670880d861e8fcbd0700b860338fa194daae9ba1245931653fa349ce85d37e2f42f871c6b67397401e190b497d15ff23e8f6e9d8637f84fc2dd4640066fee692f5d38208233e7570c3ed49a4ba032d79c7a974883fa5b5c2a113259b924a346bc4edaf717b3d272ceb152980b8606150a62f3bae3a35a639d66dc37ffbc979dda85d6f5c278a5e3a563ed865018c86563be9b878261ef8d34edd3c313500a4f170e22f386674d538b9e15930f39216a38c2a0b60380a140e5897f42d37077784cd0f1a93746e4da42a5da8de1081b8605fd1581e41fa22e7ea0d3ee0674e80e2168fdb42c1aaa3eb8aa395fdde11de5ca98ee71c50b365ef6ad9850bacf7ab011eb446da79efba3ae91fe1f7d9274dacda39b0b3bfaec7d7904eac59d72683c52b6ea091ca1374d8b744fd1d595c5700b860e04a671c7f9af919093a9c7aaf5c3d04eff31189d65f5a2aef8a08119ed1c150464c40085bfe2fc1b598fc2ebb095101d0103b995e3a762a9063d823ef6686422caa5a390f9cef5ee6c4b911fd2a818f43fa47ab4d21b01cc7b071b517438d81b86014cfe4d455820e0b9189ccb32b565b90d414ed7d315d3e61141f085b6aaea34b0c90d1f502f544408e7ed0573e1d1701d38063b239cf847018daa41b7ef75b4458d2fa23e459e9e8039668aca6bc70df1051a6466a5a5bc636e68bc8e2380a80b86045bab7cfb2814e1e3e1a40779219bb48c5d51419ce4c27359d0dfea9fbf1d193ca1cf07934ebf3d6699093387d0e0f000dc5fd2058e7ac50e67c26e5172567c2e7ba9fefa6376e44de800c8955cb330df27476d8ba9c8ec06bba46fddeb95e81b860a9fc64c64c039cbd8b23c10c706e51e0013289201111cf8c50e22781161df397fa9c1b91dbab44969aa4f8819f222e01bab90190bebfaecff7076de325dae8080bfe921fbb4ca474d45126fe5ae699dadea98a5255c048b955ab9ba1de8f4c01b860aa5729ac27a01f26924e863eea7d7b49e4f8ccb15c758ea5ac4d19691a8df31f70138e7f3011fc1e53d52d7063dd8d01a9b3800a66914956769a13ff8d7960725bf1b9073052f3ff85e57b34165702baede05d4e807bfb565a38c24e3542c780b86014dafe41c0d96b22188f0cf6cb99274e09d8ed0546bb57b28a3590449726aedf809c049663a2fe4e40b91830ac864d006a9c5b41cbddeabeef99cfddf6c298de0d482b6e945993241d8987f7fac004fe159f2206060b69d1f8f7f67f63f26280b860878790bb38b1d31707aa37b5af439d64d4a29ea64418b7c01139a26e4f297da6c61a806361e6fee8e40556500c8a6000183b2a42c54d714a143fe12492081f373e3e27e3921adeb276a8daac8b87a534c0fa1d45195d8a35cbda27f883128680b8607983d25868e1915ca8c20603bb70475b398acb04fef221106475f0fc25a3df25d181050214da347bfcd8f8292e5257014ba77cf67ee5f42202257317808f126930b4eaaf4bec801c4465ced54bd78331f8d3dadfdf2f91de294836c13e946001b860c700f20fab4ebb8ba2f47adf177e3a9dbbfb8d999acbaf0055cc540758f8c00c4564813d910e7be02e4ceaa97fb88000b3e8e6fb4308fb943fa0a3d8ee32c3a16e67eae0817370de54bec1e13193cc845cedb70e48171e097550475684cc6600b8603a3857a5e4a709e1891a13797d55c1698f931755492099926314feec955da31fcea8a8c8e52ce2efd74008f32dbc1c00c1b3d36c1f3097d806f1687eff4a979ff967a8233f923a1af6a3104c12d9d44388bece91a248bd86f253e709cea7a380b860d8704fbf6968ffd9f39f78173726dfebbaaffebd8a33dfe29a72b9a64204debf2016ca94cbecb1b84cab9d5cc168f70082530b8cfab0225a37c8cc3044c288ab0fea2f484b56a33fe6c92d6c50f254e6b1689ac6bb1429cc36a0a7dfa85cf880b86089bc906b5ea07752b1981558fd5d329f6d428bc14dfde022745303eae0077612b9c473cd66e4d91778282ec98bbd74001b61cd71448750df642fb580ce81a62ff2f5ab4378528ccd65acff67ac2175678f598529c768247c77938ca2d529aa01b860fb9de050c059a11175be23daeef1bfc374a688d8fd776e7d2dc81fe301068a3af03ad522bd915a154dc8b5b8e12d38003f17bf9f3001e8bc682e38cfc93c6901417afe1ddbfe11b04f42ca4f321f7ba73fa98f0e8c8d75781b14c0dea847a500b860bef17561ef747e0f11fd339987a9813fa8ac1cbbd6457ab8fae4841f2217de019de7caf421631372b7eec730d9210d0128e6c560948c19ab6141d6699e0283a5b98abb8266d731f2b6435a07b44360a3f5622cff59103ec95938ab74fe1d8f01b860a47fd022dda04d8dd36e0a8127be68736e47e490b946d2d88a9fdcca0a5114a930db2319e7e9f378d1b81da865d38b01a063e9994e620483b08047da39ee2fba35f66df5734e1545d297be0225ddfda34e494c1f09825eed303d166a8b702f01b8605966b41d69c0e94e202f65823338c3ee0357b024a6ef625765bcf3c20e1786258a18221e0b9a34b43380e06984d92f0183d0f86d0dfe0cac237ee38b28876dada3ae9d1a7c1e6627c3b524d0e5d4270bbe159661622821412b3c1162881ead80b8608fad3c2111494834f30e6d8a3368f2aa156c991fa4b9d55c31da88310a61248305697ad5e885404bc474419383de4f006c89c84955321716f6ceb4d5db433fcabe843d566a5e9526d29c58b38fda9ff2a13f7841f25cda8ff091c965bdf91780b8607f9df4fdb96e20e0a480a62c48896646d96982d7fccccdf70c61f2f52ab4ea2901b5ef468203f39d9d8325843ada0d00e9562c64f79ec16d69b5921ad36306ae9ae2ab97806b354af8cb63722a96aed5fa0542fff58d2e41f6aee3cb641f7781b8609cc39207797e5c37f6336c4444cf275d0afd43a9b257a08086f15867886833744c9b5753fcff76fce3790d7f25a45e004af9831464bf43e39634ecfce8da4641da78ad4ba20e540c007dbc19e391ae69cfb7809b2d20627d553a16d7d71b5a80b860e6631bd0b82c41327b582d7b239c9893cd1162cae05f360d8808700b38ee0ee965e9bd9246d79e00c234c87aa7699800c73428f7eccd77337bf79bf6b43f48345be265c38d128d2cd7f37167cadb3565d66e6a7f67b12f4bed63e5d50748010080b8410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f86480b86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080f86480b86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080", - "difficulty": "0x1", - "coinbase": "0x0000000000000000000000000000000000000000", - "alloc": { - "0x11901cf7eEae1E2644995FB2E47Ce46bC7F33246": { - "balance": "120000000000000000000000000" - }, - "0xC1cDA18694F5B86cFB80c1B4f8Cc046B0d7E6326": { - "balance": "20000000000000000000000000" - }, - "0xa5d40D93b01AfBafec84E20018Aff427628F645E": { - "balance": "20000000000000000000000000" - }, - "0x8d485780E84E23437f8F6938D96B964645529127": { - "balance": "20000000000000000000000000" - }, - "0x5F857c501b73ddFA804234f1f1418D6f75554076": { - "balance": "20000000000000000000000000" - }, - "0xaa9064F57F8d7de4b3e08c35561E21Afd6341390": { - "balance": "20000000000000000000000000" - }, - "0x7FA26b50b3e9a2eC8AD1850a4c4FBBF94D806E95": { - "balance": "20000000000000000000000000" - }, - "0x08960Ce6b58BE32FBc6aC1489d04364B4f7dC216": { - "balance": "20000000000000000000000000" - }, - "0x77B68B2e7091D4F242a8Af89F200Af941433C6d8": { - "balance": "20000000000000000000000000" - }, - "0x75Bb69C002C43f5a26a2A620518775795Fd45ecf": { - "balance": "20000000000000000000000000" - }, - "0x19992AE48914a178Bf138665CffDD8CD79b99513": { - "balance": "20000000000000000000000000" - }, - "0xE23a4c6615669526Ab58E9c37088bee4eD2b2dEE": { - "balance": "20000000000000000000000" - }, - "0xDe22679dCA843B424FD0BBd70A22D5F5a4B94fe4": { - "balance": "10200014000000000000000000" - }, - "0x743D80810fe10c5C3346D2940997cC9647035B13": { - "balance": "20513322000000000000000000" - }, - "0x8e1c4355307F1A59E7eD4Ae057c51368b9338C38": { - "balance": "7291740000000000000000000" - }, - "0x417fe63186C388812e342c85FF87187Dc584C630": { - "balance": "20000062000000000000000000" - }, - "0xF5720c180a6Fa14ECcE82FB1bB060A39E93A263c": { - "balance": "30000061000000000000000000" - }, - "0xB80d1e7F9CEbe4b5E1B1Acf037d3a44871105041": { - "balance": "9581366833333333333333335" - }, - "0xf8ed78A113cD2a34dF451Ba3D540FFAE66829AA0": { - "balance": "11218686833333333333333333" - }, - "0x9033ff75af27222c8f36a148800c7331581933F3": { - "balance": "11218686833333333333333333" - }, - "0x8A07541C2eF161F4e3f8de7c7894718dA26626B2": { - "balance": "11218686833333333333333333" - }, - "0xB2fe7AFe178335CEc3564d7671EEbD7634C626B0": { - "balance": "11218686833333333333333333" - }, - "0xc471776eA02705004C451959129bF09423B56526": { - "balance": "11218686833333333333333333" - }, - "0xeF283eca68DE87E051D427b4be152A7403110647": { - "balance": "14375000000000000000000000" - }, - "0x7cf091C954ed7E9304452d31fd59999505Ddcb7a": { - "balance": "14375000000000000000000000" - }, - "0xa5d2944C32a8D7b284fF0b84c20fDcc46937Cf64": { - "balance": "14375000000000000000000000" - }, - "0xFC89C17525f08F2Bc9bA8cb77BcF05055B1F7059": { - "balance": "14375000000000000000000000" - }, - "0x3Fa7C646599F3174380BD9a7B6efCde90b5d129d": { - "balance": "14375000000000000000000000" - }, - "0x989e1a3B344A43911e02cCC609D469fbc15AB1F1": { - "balance": "14375000000000000000000000" - }, - "0xAe1d640648009DbE0Aa4485d3BfBB68C37710924": { - "balance": "20025000000000000000000000" - }, - "0x1B6C64779F42BA6B54C853Ab70171aCd81b072F7": { - "balance": "20025000000000000000000000" - }, - "000000000000000000000000000000000000ce10": { - "code": "0x60806040526004361061004a5760003560e01c806303386ba3146101e757806342404e0714610280578063bb913f41146102d7578063d29d44ee14610328578063f7e6af8014610379575b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050600081549050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610136576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f4e6f20496d706c656d656e746174696f6e20736574000000000000000000000081525060200191505060405180910390fd5b61013f816103d0565b6101b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b60405136810160405236600082376000803683855af43d604051818101604052816000823e82600081146101e3578282f35b8282fd5b61027e600480360360408110156101fd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561023a57600080fd5b82018360208201111561024c57600080fd5b8035906020019184600183028401116401000000008311171561026e57600080fd5b909192939192939050505061041b565b005b34801561028c57600080fd5b506102956105c1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156102e357600080fd5b50610326600480360360208110156102fa57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061060d565b005b34801561033457600080fd5b506103776004803603602081101561034b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506107bd565b005b34801561038557600080fd5b5061038e610871565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f915080821415801561041257506000801b8214155b92505050919050565b610423610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6104cc8361060d565b600060608473ffffffffffffffffffffffffffffffffffffffff168484604051808383808284378083019250505092505050600060405180830381855af49150503d8060008114610539576040519150601f19603f3d011682016040523d82523d6000602084013e61053e565b606091505b508092508193505050816105ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f696e697469616c697a6174696f6e2063616c6c6261636b206661696c6564000081525060200191505060405180910390fd5b5050505050565b600080600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050805491505090565b610615610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050610701826103d0565b610773576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b8181558173ffffffffffffffffffffffffffffffffffffffff167fab64f92ab780ecbf4f3866f57cee465ff36c89450dcce20237ca7a8d81fb7d1360405160405180910390a25050565b6107c5610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610865576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b61086e816108bd565b50565b600080600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b9050805491505090565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610960576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f6f776e65722063616e6e6f74206265203000000000000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b90508181558173ffffffffffffffffffffffffffffffffffffffff167f50146d0e3c60aa1d17a70635b05494f864e86144a2201275021014fbf08bafe260405160405180910390a2505056fea165627a7a723058206808dd43e7d765afca53fe439122bc5eac16d708ce7d463451be5042426f101f0029", - "storage": { - "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0xE23a4c6615669526Ab58E9c37088bee4eD2b2dEE" - }, - "balance": "0" - } - }, - "number": "0x0", - "gasUsed": "0x0", - "mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000" -} diff --git a/packages/celotool/genesis_validators_baklava.json b/packages/celotool/genesis_validators_baklava.json deleted file mode 100644 index 0aeb8dad9..000000000 --- a/packages/celotool/genesis_validators_baklava.json +++ /dev/null @@ -1,206 +0,0 @@ -[ - { - "address": "893c4d601ed879b4ad36fc31f0c0214d547113eb", - "blsPublicKey": "3695297deb0f970e1cd8c64a852b45ad788e151734ab05a20206be63f7f42817fb5e3e035d7f9dba56917a0bc75a3f0061e767a5cc5a60469709f170f4f7d76dcf6e30f04a520745ac8f3f131d6b854ea2a899c3317cc48bf06cdb07f4514a81" - }, - { - "address": "75af50cac2b2eb330b975c1b999fef571c870870", - "blsPublicKey": "6b628400822daba0c52481cd1f8708056c40c392b362a9028d17032b6324b114620118a2770e0ddccc717685c2380600d035299ff9fc354180d251acaa778cac2a2eb64466e977204e582ea1342c0100c01ff5ea558be47b1f36cfbaee7a1e80" - }, - { - "address": "ffff741c41fb487f4d64fcc9e32fbb38e2a8372c", - "blsPublicKey": "f6c310b565f6f975faf4326707551a9154b848a222c14c6e18b87c0bd9bcf3524d95b70d5faffe1d911955186f160d01c82d4df63cc8dbc52ef2e106c89d2b838c57a4e6fd033d7d4cd49698111fd78321a962d03b1a31eefdc84397c0d51b80" - }, - { - "address": "c496e9791d39a6f0ae54ed52897e581d168a5b45", - "blsPublicKey": "baa5538d5579ce32668fbf4e80cd9fd31f09447ba473da1ae44a51ce6feb4f46d8a14008fc515fa7e0e9d720c83b7001bdbfbce56284c382c5a267e7a245daeaa9e2914dc92cf2aa2ebcde339e309c5d1a0df1533cbd631168fc3e4a1d248801" - }, - { - "address": "b182f37daee2285f14b4091b702ceccb00d50312", - "blsPublicKey": "5a13510aa9b74ecd0bb7d8bd7f65dd5622ff4a61eebc1976529a26954d70732d591589dcf49e3f8a87f450642336e200391e1e8b57afe3d7240b80020deef9db2d9b260fc3f30ab4168521de586c211baccb505b75af030d47bd1d6fd49ab480" - }, - { - "address": "beeb24d10c9fe58715a0c853db8ddd8e00191771", - "blsPublicKey": "382d76c49b99ba0d0aab030afe569b89288f399c727e3c1dcefbe1208f0c2d86498f62e1fee2d50486e2d6aa0d61130172cd07019fdfe79cbbec315f53465d9a8121fcdcfe71efede293111915281e82add7252b88b540b3a0dcd2fcfec91c81" - }, - { - "address": "aa3b76b6618afe574b278da9b71af0e66aa6f646", - "blsPublicKey": "348aa54a71033d583a29d00e3dfb1f696633c6520bc71099fd26a228d1882f380ab86ef19b7efe544d47ba8aeddf770125075f6c15b82611a31e746668c1aa8af2355efe6e4cd297c0f570fce18ecc2f274bef5115a8d8ba9a18a6563e6c6181" - }, - { - "address": "e2368b04a1d14f286faf8c90153e33dc0b0879fb", - "blsPublicKey": "17a5c4c6a8aa852ab1ac7771e3caa6546da92938bda6d4e0c0ea05da85adbe08ca2ee58e657a82b619d1a729b6510401686ca15382abdbd856716fa867573c35ab8605d2d57b0573ff589c087cf57e5408cbf7be57ce5946a6455b1955d9d300" - }, - { - "address": "72bda6988c4551083c14dddd2709edee96a9b4a8", - "blsPublicKey": "9887deb26c20c4b5b448e04efe7b18781355f9648feb47d978382aa3c789f545416d20bca757df66b70867ccffeba0014bb1b45fafe0366aff4d513c023a55ee35ccc5a86d5214f813996e2ded810e3cac11cb15b7ca0b97aad1a307897d4d01" - }, - { - "address": "f0d17b624521c0a599b063d73a73f9719307b48f", - "blsPublicKey": "57b5158540d1672de49073e469e5426766094ce6514ac29580803ff9d22cdef3b6fed28a8ad9de63bf938c1c7b0e7a0156fb03f5363d09bf337713d8d45475df48ccea0fa793f591fbb62673545fc846c04e6aa9e2eaaab72c3b9ba4069ea280" - }, - { - "address": "38f3eebb5a820ba4b83b1f6a324c09ec1db2d2f9", - "blsPublicKey": "720216212176780b12cd297d1feff6a964329448d821fd69e0a4fcc53c4edc00ca9c89ab2c35abe7b68cd47bc230bd00597450ca0bea04562f78b0102d406f4b651957989c1471674eb16a531c2f762c84c3432ccd7fab87b0a185a942d00301" - }, - { - "address": "2f916156a2dcd5dfb6054eb62a677c55c3a4037a", - "blsPublicKey": "68438d70fb61a2d0adc3710b619aa5f9a603168f93bf0504401464df3acb14cc1815bf449b7f8791fef7e309b60e7b0145d425515d1f4f380b66c256a4218700ae48e2d2185a636487d6f531f546b9127b957084d0821acccf5ad0776b06be80" - }, - { - "address": "ee80387e93e4d6d41c4bf51623bc8a42ba55a449", - "blsPublicKey": "92b17fb70e62710f3b87642830e23258a0fd1041da9606c7eea7019f86da50ff4cd06ad48a4d0ca93e62a6c7ed6c5e0036f4443d0cfe9122156a346836a9163404d58856bbd447939189bf1cc8a7ee8be156415642992f8e0659526d15bb0c00" - }, - { - "address": "d32e429FE2155971825E14E2fd89785301ab6Dc3", - "blsPublicKey": "bfd4b2392664c68bbd30d6a77cd1c7230e340ac65ecc07449c0d704096af06926238c60e7764ffcd0b9a53d82d7050009cfd9481ebd7630fd2540b834cef70b5276d07b75913a20222d74f36db8beabfcd39f7c5d57c4a28f87e8e737123bd80" - }, - { - "address": "8c517b3bab0e2d65d5cdf3750ca360ff05b3fc1d", - "blsPublicKey": "2a10c24fb6cfb029650a90f10f6586f26e61e3a51d68342785862e666f6c730bb929ff2c5a20f5ceff41cb53a2333c00aa0e4b0e47c821c668d6b84fac85c5b5cd360c53dfdf9a6c48e0f4ff8c3997ff191463f90fa644fc2870174d67885b80" - }, - { - "address": "62d56ba5bb3b841fade256d97e7d4d57364fb881", - "blsPublicKey": "8aed791b4381c7bd38f8358cbb7f64bb6b74c34b85b27026745df7cae91f5cdd50ba6cadd919494ec9849e628138870188ef21da8282207be4acd30803288e2674a7c46322f41f3ecf685f5b635970c0d19802defc344cc4023f8e41e50e3c00" - }, - { - "address": "beb2b0ea812caaaea3a1f894fa9138231e2c7d38", - "blsPublicKey": "5008d7aece8407c044c4a7a77b37690a08b0edbde0942446f31e3362031e689b30872d8732f74dd3e45bbe85c072a4005ad20cf2d9e0824eed9a607b980d0cd5d160bcbd5ffc34a6a87176e257c927cd419ac080df27cce888eb94c7bc5a3880" - }, - { - "address": "430c9d55CF6116c65482379c039584B9b965f323", - "blsPublicKey": "a4ef4602775c99871c1f910af02cc997cb6f6b1524450898a1de0a3369750ce17deda194ce40c80650025770e1c60a008916618d314d7008a44e312f2f032fedd08177ef854cf78dc269122dd7eef415989e975f13d501830df4ecd3fe248700" - }, - { - "address": "821a6b00d9f658e1732ce741d91984c688e25c5c", - "blsPublicKey": "f01e9ee01d1a76e596827b897e39a1e497b00d6ed276675201e81a07509d4043354c89d0ed515098b0730958cc9dd200fd9cf9d1f2fdd7823937af05e03eb1b043de63e2c8ff7bfebc9cd4f3983243bd275d0266bbaee5e70244126687470f00" - }, - { - "address": "8339eae8ee5b8ea60d80711c9fe30ae92c0eba2f", - "blsPublicKey": "1f599e48d2f04e623c42ae66d379f15ff8c1a3bc4584a27f234fc00e7feb64dcee6a0faa4cfc3737e507b9c38d640401b23b2c6fb9bb7f00a2144b8031b9b2446ac121e7ca7f06e0b6e084b082ada9fc31837d094b0d6c3d24965a9a61fa7a01" - }, - { - "address": "a5f837aa6be966d9f293de6f8cc65fac7064220f", - "blsPublicKey": "c2cc4ba57abb3768f552b30768ad8de8d6b934d8fd2eca699a2b2f712e8d56b50ea2e59993175a396e471e3a6028b30054cf156b0c75b9df6ea2e15e03811960aa5999411522b01286bc1cf17e4ef366a48e3e075998394e090f46c1d8212c81" - }, - { - "address": "d2462858d04dfdb0c7ad26dfa21933526491c1c3", - "blsPublicKey": "3201cd2f5f5f41b6949a03a600347bf9920c891b883dc4c8a530188fec4f98ac96d6caf9e87a05c81962760c20c30c0198745f18efc87a19ec94a06cb01d72313a71f4ff30e94f04504e609cd495ed4b78dccdbdc6ece12d0200996763439c00" - }, - { - "address": "42a237fd620f714536d6f63c0f46d092c9ea0122", - "blsPublicKey": "b1d7e87a67d355c42cf7db5c599da2ce9624372cb941f338d68b80bb8376fc8600e6d925d9902f32270d6372d4215c0068879d52d16dda84ac2efbebbde57d7ca5d451f269aa9903926163d7ce75b68d2547c34e07303b9db69d0044c9219200" - }, - { - "address": "dce0096c358e90c4645d68a53e897416e786d05f", - "blsPublicKey": "872c5c11351fbe7f31bb38ff5f7b07aa8bc4902a06b81f4fe70e7bc5be86ad260be53c26ef3d1e6293e3308c33ef8d000c13182ad835adf86e816496d6519ae00bd607f6f5d974fab0792802d69688e6ef37078285a1a2e9f8489bfe5a87e600" - }, - { - "address": "d10ddf202de766dbaaea7c436a90f5aa71e5bdc4", - "blsPublicKey": "6afab29c7f64915ebcd2851799af2f43cebbab8fe051965103989c47e576181533f7bf64619a4ee50bd787bcb65f5b012d60c2eadaad3118cba6088cfb9204f5cc465d47dd4c834b568f313d5b0689c6b6f3734cd19d4df40185d007b22d3681" - }, - { - "address": "2ec7df44dbbc3d458acc4108aac8d1cb0bec11c0", - "blsPublicKey": "55470892fbef78fa87bf31aa738a58fdca928a16d99fff12e8ec3d71fb89489286206e32aed5063f1fdd6294f8a3a2011e19cb83873a777741f3d8521ea33edac732704e36f1aac01f212eaf72405cf8d980dd88bcb88751a6bbe7207a5e1081" - }, - { - "address": "b8f90aed575898c38c11deda226e1294f4d9dfcd", - "blsPublicKey": "207a4c7a86274921d013932e2f88ec795dfcb1f85df6bba7039fd14526cd44245f29d5916d17bebf40ed08be3d0541006fb3443238819cdf36eff79d8706ceda92b0b3bf05d6dfd9a723da2685acc34e59928fed096dea64f742fb55c7f34c80" - }, - { - "address": "8a63fE13A4be506e8B51d296f60F192458672E62", - "blsPublicKey": "3891197bd1712a3cf13fc13f2f2308bb4acdd4e46e3a62abd28a8e3add64ebcabfb939c743e8e4d54da2a32c39719d013ca29923eb2c685ab851a4f644824d70b1fd36812f513f5f23fa8f82ea228ba2d8f8b771b109e99e1905e16b1899eb00" - }, - { - "address": "80be4e53c6bf959445598965c2910c2c91ec81f7", - "blsPublicKey": "efff9b35b865ad56dea6f6c80d96ae4ba88997a60451b1535ea51ef6ae1d26a1c25246f33139f64046909d4a30a90f00a782c6a5a910499b65d7f2c3064dca95cb6dda83c10c2f9dc8f60d1afeb91c067205dff722dfe964f66a9a98e4047800" - }, - { - "address": "4663bf9f8c6b32f095126e138678732c0d183f7e", - "blsPublicKey": "6dd6f3f642e00ffc73a2d76c8f58128aa434b526c0487487f193b6717665a2eccff314d7d0769dc17fad47db19981a00c8a11f156a2bdb36164b479cb1bcf636896066e3c3b561c478d357b343bfbc6aed51b08f60b8f804ebd78e2efb525c80" - }, - { - "address": "bafa573a3d5333fc88560de1c312992c56d517aa", - "blsPublicKey": "8202e06fb2d18ad9a85b3af760290ca4aae79fe2d354ec4c462f65e98339f9bfbf6c24503c73b054bfa740ea595241011c0d599d95697238c700a380326dea544cd7b085a3b8db22ae900ac82a5c23ade8c4290e022b0e425a55f742352dc480" - }, - { - "address": "8a0d880f275d3741f507a0180E843a2805eC1e2e", - "blsPublicKey": "acc4826a9317688bdf782adc5acdf12656ffc2f327ca699418c287a15c2c22e0d16e632e592f5b0748b40a8e374e33009d8cfdfef7f81493a77843054cd006858b1b217043954423bb0924d0387b6609a504e15e6c054fe1288e0bd337253100" - }, - { - "address": "cc8c30b74073f537a6f790ae68649788a66f2d71", - "blsPublicKey": "6c93b4d43d69c248efadf8d03a4c9672ea222830a1530b29deab346933fc4492a211223c446ea24af059d9528ab3c100f0c4769fb226335489969277140da7c8c7f036d76f73c1d5f359744018b76b13c0eb07812f08923649e4a45b3b69fc80" - }, - { - "address": "ba7d40c43dc59e2686fb38edcbdd69c3e53eba34", - "blsPublicKey": "86ef363fcabe2e3c27769de9974f4b8604b47cdb2fe57208f0a59899b77306b7770f7403b222b6222efeb67747d06e01fc2ac657a21f37ab982d8463ba9c7fafaeda20370ec3f6cc565dbec4a69f59f9d7404725e3b701681d41a870b1f42281" - }, - { - "address": "1db8f844aa731e4a20e139c7e7ebfeda26888cc9", - "blsPublicKey": "51026c0f52d8612414359ee4e6049a275387d3033cf51a8e23b3e037bd7006d916017b5253da7068532e6242b1d96900d8130a60b9b0b3ecb06a08472728bddd55f778e485188c3717b911039ebe3b2cdd89573229bdacaecba9a220b2decb80" - }, - { - "address": "3acce236f234aa330395d50d6155f86c51697318", - "blsPublicKey": "6a2cc88ae37c395815dcedb56f5ee6b701e06e97bdb6232c2b0e21f719a1504d0f3b259a63e2e54d6b1a27cbb0b051007f0c39d42f699cfc608c25b636ea221500d0eb75fe0f26d35beec47e1161675a7f571ed70684778ee7c4bc6221d8af80" - }, - { - "address": "cd97f1e7cddff4523f03a5072e9be8ea7edbdaec", - "blsPublicKey": "c5f05101b67ffd245abb878fc8d68058e3a65b4672453b90cb116a0cb8f59879a73944d8a2c25e8a2865e07e1e4e0100cd255dbd7055b5228eb1d4cccea7a1288ef83bab770633b0054f8c8d9ad4e7fc15af631c2b2282337faddb2220e54901" - }, - { - "address": "537bf2c6227ea6ce4eb250da02e6a6aaa3de4f7b", - "blsPublicKey": "3178c750f9274f0f1ea4103997e7d469b2ef4b9dd2f1dff7dc33ae5aaa5fdfa32a9e44e844de658502fbd8925e9a8a00d4422f22a7a5c3e4a790d21334eb70a744da6a863c4e060481781b8bb3fd1e9291ebfb548f7d8ec122c2c0c43eb46000" - }, - { - "address": "48cedc58b10af13d688631bc3cb78a05b8a6e56a", - "blsPublicKey": "7983d25868e1915ca8c20603bb70475b398acb04fef221106475f0fc25a3df25d181050214da347bfcd8f8292e5257014ba77cf67ee5f42202257317808f126930b4eaaf4bec801c4465ced54bd78331f8d3dadfdf2f91de294836c13e946001" - }, - { - "address": "f410a55e2f4b49996a1cb884c3107490aee09330", - "blsPublicKey": "61810f2366f415b7b67e0ff9c82ae55fa213a95ff61df8718e806931ce135c0324462a33ccbde34ff901025ac334640064b41f7854c6eabcf3d9f7a4e4ff90522a4ba2681a0df03d08c67fb79f0fe98cd8c6f5ad3df155a0210ff84fc93d1500" - }, - { - "address": "4ec65178abe63805b2b0ec2718280454d9b6353d", - "blsPublicKey": "6a50718246d5c167429ce48b757a28441b217eb0903d762a3039d0ee59c00584b05418920be4eacb2fe2051d492a3d003a2a00065986e15815c26434c68caf177cbea44a38a886e86b34dba8a17dca43b729b9d69007e25d735e0ec62f7b6d81" - }, - { - "address": "23836969f0d095afeb652c75523f740898e0c462", - "blsPublicKey": "424b8239213c6f2c3e181b815294b9dd78663e29ee1234e1511e584b7b736571a6799135381cced36dcbd12dd19a5901f479679592608ab7f98aa1f607a3fe4b5b29a6580f724086610c901f143be653dcaf9fd477ac4d21d263e8ad8d048681" - }, - { - "address": "23e15d949c13e3010b75afd19b1d3b294310c7e6", - "blsPublicKey": "f03d1c933feb791285892c9e6552bc6ccf07dd7f66862ff5554844db033c17a005087b5847718d4611e3ecb293ce670144a99a13ad3356ca56535815a0c6c21c2f84bbc0b40c78f6b63137a17709fa4be124be10e90a42bda72aee977ca86881" - }, - { - "address": "0ec5a403212d732d8d7ced050e9510f6327453c6", - "blsPublicKey": "fb9de050c059a11175be23daeef1bfc374a688d8fd776e7d2dc81fe301068a3af03ad522bd915a154dc8b5b8e12d38003f17bf9f3001e8bc682e38cfc93c6901417afe1ddbfe11b04f42ca4f321f7ba73fa98f0e8c8d75781b14c0dea847a500" - }, - { - "address": "0ec5a403212d732d8d7ced050e9510f6327453c6", - "blsPublicKey": "fb9de050c059a11175be23daeef1bfc374a688d8fd776e7d2dc81fe301068a3af03ad522bd915a154dc8b5b8e12d38003f17bf9f3001e8bc682e38cfc93c6901417afe1ddbfe11b04f42ca4f321f7ba73fa98f0e8c8d75781b14c0dea847a500" - }, - { - "address": "e224ceb83a39d2ffa7eaa0c501e6954db5667e59", - "blsPublicKey": "0fa447ead6255657aa79229944a3ddf36984c7b9011e859f90bc6567ab61133b27b6bfa3a5e322dcf36abff543cc0d0131066520ad92d12b8603c25c561bf48806f178a995d233862038c46e81933e1ab0a7211b9b0933499cbc5867db736481" - }, - { - "address": "3c8afff5c9332161a20db995e2c831baf02d9f91", - "blsPublicKey": "2e45f40c799aec72e87e0ba4713056dd17cc9bdb29bb221c8fd6377336ae773afa84b8c0bb8f1f2edc88975b8ec986006f321462e28706618d690d24337a9e1c7b96e74d8c8f2fe740bac461635b4828046227f92f97b13da8540bdcc2f1a380" - }, - { - "address": "0f409814CAd27cE583De0d6a10Ecf53d48b9535f", - "blsPublicKey": "2b8ab0795a174e96061dbb8c32bd38468497e56379b2ac79f6a7506f711b817cb57c8c1d8743d88c436cdcde3b51980132c5508f79cfc477bbd1b94fefd5c408a7072e85041f17042c1ad055c04e67a780f497e60aac3c38ddb2f0004237aa01" - }, - { - "address": "f6a969790936c5285f7a7d1af642707d0c8e2418", - "blsPublicKey": "3729df3ecff9e168c1ab2b2698251797494847ee14bffe9c4ce121d90d381b0d51f7208c793f55a9cac9d50e25d63d0018ee5daa523319bbd5087dc35cef8ec53338d810adf8b4565f39fccdddd7596a63198f045a2f3d92bd0b72b4487bcd00" - }, - { - "address": "7a450c89257bf0ead22f143493250907411cd1d6", - "blsPublicKey": "44a466fb5cf01c878071e12dc391753cb59005e39c6604fa0d1444ae36518df771f252891072c26652e12a5a5b1f3c00f479f3e3ace6412768ee5729825bac3529cfde3b44cc258b847dbd87f6d55dd68124d054314eea0a9169b36e46e34081" - }, - { - "address": "fb041f37e22b25e30e10cfd662e6a5f2d1305476", - "blsPublicKey": "c6ec185bce68a0a1fc78f78a5a9da12d39635f94b6981a64d7ed7a095839b6839da577383ddf9ef940d93409ec305801cda7a06f3c3adde48e9060ca396bd8a2821fbc435842bba5ba1dc0b81cfef04cdcf0ca7b02b6e4d70ca9caed84387080" - } -] diff --git a/packages/celotool/genesis_validators_rc1.json b/packages/celotool/genesis_validators_rc1.json deleted file mode 100644 index 98379df5e..000000000 --- a/packages/celotool/genesis_validators_rc1.json +++ /dev/null @@ -1,328 +0,0 @@ -[ - { - "address": "27F326ab753D62CDB55018c62E9ee7E671Bbb121", - "blsPublicKey": "05f784c52234d0c40ab13b0636c5728217a8f3100046593c30271d39d59fcdb9a0053a874710e9c65e0d8a030c16a700b4ec430207cc5037c5e2698ef839fa0b7a4372f4b5217deda2a8df087e3b552f300016ce9147a2ff4db4c8a87d77b080", - "blsPop": "8df6590b8a584b3f4bd47d208fc7061584188c6f74c9271dcaead50adc6017c3e4a552820077f8971858a5a1aa8e3680" - }, - { - "address": "7eEC94733d16B96C6fE877464630BB5Be1E5c3f2", - "blsPublicKey": "d3f640c3da685893c41eb6301fdde2920c5a09296438abe5894074592f27547fb4ad02d222b1a330ff5aea065eff5200973d4fcb57808d8d9b09337e09aec279dc3337e758c51a3219596699006ee3683ff0c733f16eb917fad37f7f5d505201", - "blsPop": "782c90e7fc352f0a99ad5a793e7dd90a7417d2c9f69c02f4cb6821b147a1efaf1dda74b7666fb27b5e23082bb9138a80" - }, - { - "address": "f0d17b624521c0a599b063d73a73f9719307b48f", - "blsPublicKey": "57b5158540d1672de49073e469e5426766094ce6514ac29580803ff9d22cdef3b6fed28a8ad9de63bf938c1c7b0e7a0156fb03f5363d09bf337713d8d45475df48ccea0fa793f591fbb62673545fc846c04e6aa9e2eaaab72c3b9ba4069ea280", - "blsPop": "326ca5e3a23a45e4c89e5876682ebf6c53ded5807fbe758c66523c8a3bb335d0d8acca0b39ddc971d269e4bf2bc98c01" - }, - { - "address": "A7681958B7f07f4fB8BD5b0e075FB2Aa2b021d59", - "blsPublicKey": "ca75a4c4e1f2898c0ae0ed53698b0271d1f8869ecd945891ae6a9b02682335af625c29f80572b440f91a3a343f3ea600a49a426960b6c1c5dd7b24540ecb745329312dfdd525fd173418c846f0096acba466a27446114f3a2b2a887986846b01", - "blsPop": "0007ee1e065a5d71e524dc532824e2e35b2c3788455eb6866f375cf738cce0abfa533d9071b864f5b8046b09a9049001" - }, - { - "address": "ECC20b5f3D6cDF41fc12707AD7872Ff64256e297", - "blsPublicKey": "b3dff5505fe9ec48fa11a67dbf166e7d5ab3473ff9f5fdc90c690eb1142ad687b17eb8ab0c08615c9397b351c53e79016d593d588f8c607b2d1136713d05066ffd8a30589357afa54a0a7ac8777372787261dde126c4f0c04bf741f809c3be80", - "blsPop": "b33378a91d0bea36d2977443185e8c8da2951e1cc7dd24121d66d71b19bd47b6c9fe4c7f28e544956c62126850637901" - }, - { - "address": "e5617da4dfa6ce4912f1d39889fe2dec2f7e66b3", - "blsPublicKey": "451da71ff5b1e9b4fd587fd76f53808191096cc5869596eda8f3ad697426a98a659f5f4818e57866d4b0dd90f0684900742a167b314f0276e5e6a8bc6f40ce1cd1d35c7f9be56f1240de596b30a4b40010dfd21b7fc9aef400faaa421e27a080", - "blsPop": "c4f53cededae924fbaaa44019f122e75d9b1f8d98a177da7d52109aafa25cb33c272d839cc6fbffe4afdb5a5bca35981" - }, - { - "address": "39ec4f2a82f9f0f39929415c65db9ea5df54e41d", - "blsPublicKey": "277d5eedd8cf7d549296a6f8ad2869ec6e90183b9e8ebbf49a9d3ecd817757b50c6acc6cab9f0dbcf4b87251b6e82a0192a00c1e509225ec1ec08dcbeb04ba2808b16f72af90f33277e614dc19383256b3980421441ce3e75356ee35e5f62d80", - "blsPop": "1880725666ec3175a7721142a808bbb654a555dd381d563f907cc1e7aa82fc04ade06a471543de9001b6ba6f003a7900" - }, - { - "address": "341Dec14b7A56c242CE9Cf939815ec7bb1104244", - "blsPublicKey": "07431d3192f7a273382b645bc300cb0161c2395c005bf389698ce4a3ac56cffb9405456102f5b6e41b42bb28e7cb1f0141d3e1be1b066a94cc2befe88b0f5eef63c60a1ab8a1f0cc02e73c0ce5aac464332d3a2c1074a5126807a75323280301", - "blsPop": "1e913c644b1699c791805527bfbd539de4b7148e28f9999efa0948136c623d8a0139493cbd8322ab247c40fb61397c01" - }, - { - "address": "69901924e6c045a03cc163c6b8ae8af80fa1ee80", - "blsPublicKey": "0d39e1cd00ff4ce5e41fa9ea90526f3e3540b64ba52954e5682f31ec20360b2995d5caac7cee778ff7c13aaca74b9b004032f87a331867e9ebc7ed06c5b77707c88614714f2e0ed30c85c519aa823aa9d1a7a56766a294c7802aad300b408280", - "blsPop": "8cb085ac2186dfa767ae27fcf9a81f78e7c8d26dfe10a238bb1cb6cf708ef0b3a62a08b3510162d97fea4578e9326b01" - }, - { - "address": "0A6641d4736767D1f2bCf2450200eF384391B441", - "blsPublicKey": "ce9efb226a3c085071c7aea84f66040dc16a1600893eb1e6ef507fa72c6684f24d2c3b4ffee9881142fc41cfbd6b3b01933838ed7bd05c16450cab703b12ee623f8745f7f618981601a9c4de1337fe881975bc8572536281b9dcc51400177680", - "blsPop": "d9e2c53fc104b58d04fe62288f432f14c7dc6658c27acb803cdc98743cd18a8b7dfa53b0e7d77105b9ed0d2c0a22fc80" - }, - { - "address": "66bdb4D2ff2Ee4C68517e6fCd25Cc3034C869160", - "blsPublicKey": "075724b0f2fa9ced3440a76107a53b02a0b8b5a5a510d94b02b5c0696db96910204d54ee3138b3e5949464585d98de00a2964d480ca31adf09c962802895ea160d195bce583e59094bf7c11d33eaffef12cb999284bcf842bbab2c87647d8801", - "blsPop": "3833035453c03ca035586f536eb32b33995e9326647b8ec308b4e0b9ab8eaec13c4130e858dbf7a3a01aecd157960a00" - }, - { - "address": "606311948f7426Ddfd23C1521b15eDDB52E83B29", - "blsPublicKey": "3b0ffa0a101f959879b7e14d830862981d6c311ffd440f214eee0a2891743a25355e9230266aeadbd20f3bde0ccb30008bf326df8fba9b701d4764ad49663da19417132edf4281df4560715649491d9794dc64e9540d16b51b362e139c3aa701", - "blsPop": "363688de4b6c0aa6a53cc337dcee033ad9f73fb981930e78be0bbeea593b9cf94553a8512f8049a1ffa17d88d9774381" - }, - { - "address": "4CB90Ebba92141eD3021F5dC4e6C8bb642095846", - "blsPublicKey": "1a65e75f0f47d7c92da92de15372a0052338b952cc1307d5ee1596a670fedeb3b5ac8bc690f3f5e5f34fb8d18a5441011d6023e3c2b343bffc655972102a7181dffcab47bd0a2d6d46eedc6f2b70cd64025715de2b8ae23c032e61b380663c80", - "blsPop": "7bbc9c317c7a406cd3ed651f81308615d26ec8701d2f714a0b11f63e7a67a779f43813436827e9aeb1f011310b962881" - }, - { - "address": "8c6F9aAd8281A21e7f6522602f2D6469c950e0BB", - "blsPublicKey": "71ca0f2be942a733074e8e0d92ae0adc2617bcfe503b97f8339c8f1c498d85608fa5966da7abdd9651c9ce4e3411e900c4d65d5c7d858f1e5ee212c9e543d3727aeaa9abbdcb68848e7c990c06aa70a4bf2585959943935549e7a9e2c2ba0d80", - "blsPop": "672a89e0df5f3c3b470d9cbf24650102c5f54cf61281b8df542d70dd81c4f5f4c1cc27cdf59b2e6ad6a133a965982181" - }, - { - "address": "2a1BfF2452AcA1ca5FFABbD34b2744109d11E4f5", - "blsPublicKey": "0122d3f6ae5e2bc6fdee3cd35a3522ea519bfa6f365451fa275c4688bcfb5cec418fa053a8859981e973ea273ca68f014e840d0ccf18cc7c498742103c3116732ef197a9f90f50bf64f83754a86ad441fe9691bfdf384a1aaacf38430a2b1001", - "blsPop": "bfcafd40590a90c488358efe8cae948f248224bbf587c0755820a6c0870bdccbf211238484178828c74afc08868e9301" - }, - { - "address": "b4fa2d21b238e12ee4a863517cb5092f2330cb1b", - "blsPublicKey": "1135b86a2587c75c55db8274e498bd3f2887a1a455a665b8314655124c5e8197d3ef892f3dea2bd80b047530f837ae00dc263da929f0135a4f8ee73d47d5c2ffcaaa7b1e3a9cc59e496feeea2323e5eb16c9de2e3b973c35c0a82ca587477201", - "blsPop": "a085173ab5a1dd464ead8dc7c54719dcba8a61c432db686c68a883e3aca410d16b84fb611e0d080c6218cb3f94fc8e01" - }, - { - "address": "42d441b6793e6162b979fbf6ad0af0063cbec96a", - "blsPublicKey": "e162bf706b79405326d52e29e2ea247a55ebf69ac34900e4e1249c3fe28fd3dabf40d7022f57bc7b16bedbc78bb49000ba7cd92e123b69309a0572cf49b1bdf4c5525ba656decffa5da91ed4fb565d384979e9a58f72986b654908bcc7308580", - "blsPop": "77167f6e2a1160d6956c5c96a66b98f7409e32969e5d24ca2d28092fa5fc603c2ff7a220806ea52dcdd010f7e28ce680" - }, - { - "address": "436d12F639A32509685080161Ff0365Fc15545f0", - "blsPublicKey": "e9dbc5c1d073954ad6ace9afb19d8679e8c87fd12cd1356999a8e167390f3de966f3485b500c40c61f829e12f56512001b4d4c4fcb19737735eba15d24d43231ce64cf348de3765fdbd01f4612af6ad7ebf9fafb594ade18a7717c189e9c2080", - "blsPop": "c25e9708b2a3a6e1e5fc625a8a45048fb8b2fae9209346643d3b2ce4ba00948714eb4131a065309d8690f3aa689a7980" - }, - { - "address": "e0c5f6172673ad70a76ff264cbc0df783930b47d", - "blsPublicKey": "bd8e3d6ad24e5a7e4f084b3142c6bebe26d248e09363a9bbfc9cd07ed59a65bc140a39564f6ecdf287c2ee1ed57a930035a92306b6d5925af8785c813bad6113ba42da88d3c0586e438df75bee506bdf9f10c927493524897ba485946f976f00", - "blsPop": "4c65e9a51cde701d3abcd015b6787f9931a57e3913118befebaf6d7bffcb74ef8b66ab8e4abcf0504ce2fdd33b277c01" - }, - { - "address": "21245b0A2c3235F1108d1Aa01AE376849D36e684", - "blsPublicKey": "30feb59a6804a2df697b3a40c691f176575ffb0d09fa167a59642d041dfec97e97414ea7abc8bc7bdad5f1a684e2bc00fb2c01bc03aa9e8caaaa82ca3210de31f9c7abff6baba5e08e2dbdfa85953ac39bf3b895627e7be493fbb6e346061400", - "blsPop": "1e953a19e0d18da7b791b7cad62a57e3ab0954ab7f3cc912a9b6a7b56801183ceaed7482a826ff97c9507cf320ad3d81" - }, - { - "address": "f27bb4eabc4400a1abe9d80d7537ab0ef1b058bf", - "blsPublicKey": "f24f6f1e6423fd83d1ef275484a5950fed90794d7bfb6224de768bf716646dee263de0d9ed4c681c0def78d16df0f000f1e17b8657f1d8e30dcb7e94cd1c79b9c82d8f04252b078ccf3719c7658dd82b9d93e02671925b5aeb4ae38163129100", - "blsPop": "4de6ec6e768781729d0ef2936ee8f64df678a58ae58bdfa90d9897e1a23471c95af3aa88271863d55d180f9f2088be80" - }, - { - "address": "8440e805b89f48c932265e3c4ad033813669d87a", - "blsPublicKey": "f6a586f1ceb85a23980bdfea738678f5906de5303a7ff6ceb3ad675f93a84fcc502275fd7bd8fde4de89fd381cb8eb000b3d496e248208d00eae4f421ce041d73789e794a372ca788655eb5413c3b7cab1c993e47ff6c568ca4da484bac88b80", - "blsPop": "e9b48e137fa2b0277085b34863f11469763c280a0672545edaa51c56c0cee7d2ebcf10571b561d71b57f1fd3e8551701" - }, - { - "address": "2Eb79345089cA6F703F3b3C4235315CbeAaD6D3C", - "blsPublicKey": "86ab977d6064531b136aba2fbcc50cfb332b939e0af22c7ff3800c804b33aad998ef69a97204076028a6946d627d2f0086992cba351fd538a91986253884325aba6d66ec1ac10eb8e18330180820cc388c22de7d64f9f0592b74ee5b35745a80", - "blsPop": "c9e3a638c221d41f4568a6f9b781e4314591a769cf21d1aa32370304a5a9c7228c1d44d3a48c489877bf059fc7ddf200" - }, - { - "address": "3Aa1fa695aA89958EBDB5346d6760B72250dC1d7", - "blsPublicKey": "fda02a60f25f87c0fc86be0bf52bf1d0be37db80661a2fa35c7f52a4c5f5edccca04768c762caaa2303f8cac2ba93e016dce7c8382e3d002e751e0bf33563eb8f6e7937ab2998300e96f5ed3d857d081ff389c495febaabe836a7cd06012ae80", - "blsPop": "d44c9332df502b385aca6d7a11ed02bce0862a98e3a0943c9c40c014a357ba1097c48b0ca5345bccba65025f169b0c81" - }, - { - "address": "173c75C8F1BE201cE89cF426Fe12c9997D709626", - "blsPublicKey": "9271a103e5971edd694b3c6363a2517b0676849b05660094baf240ea9677e171169a8eebed5ad6000871b4f42d4ca701b74b10f91c0de059d225ced0222e391cf7bdb5934d1677193837d5a1f17bb710f4747956d819db51c817cbba53324b81", - "blsPop": "bb19f1e1e399faec8d291d71a31718b508e782f21111248ad2a9fe2aaccb37df33d1b8647974040649983516a9febd80" - }, - { - "address": "74288dbEFa3a55986c039953b67139A466474fC4", - "blsPublicKey": "719b2de30cbcdee6e62445b7c2eedb63520beb4cb6e4a55f7e121a5bc6a1143e1322d3ffea28ab624d30f6da8962b8003eeb056df8e46a49035c0aaf139a372e954d8ebc3cbd2d0b2e5727d54f3f4fcd0e95dc29bfa9f9ddcda98bbe8107ae00", - "blsPop": "069ec7a9207444613130c1984553081676c3675b41c5846c4719e45f9951e686b0cfe3d5d8323d4d4c261d5fdbb03180" - }, - { - "address": "82f0E7879314516952f7961b15C63FC6B2734DFB", - "blsPublicKey": "b054d545899f55cbb84853125d50ed06211ace3eeb6160a85583de508569e65592f5a221a000cb99997c0dd2738527010f2b1e83eeb7ca41c40ad9295b35f1172004a63567f140c1d2b0e04338161e8f1be88c1543ac75d587e42c3ed7dc1880", - "blsPop": "97860ebe1169d6b1f5446ee5485bb698fae8dba39891852c770edf040cd43b5479532efc28e499f908a4f256b7601181" - }, - { - "address": "59F7b67e6BeAE0223DDC91Eec010b670c553E8e0", - "blsPublicKey": "e8de954d3100b125b2a3c1e4a81e3ac5f4b38f85c2ed91d752c507d4a37c338ca215e474a48511c599407b85c01d37012cd5012c74c5c0c3f88b4480a73bb52d1ff49848ca014f54cde1a891e6efa483b5f64016a9303515806c45d9f79a7e81", - "blsPop": "90dde5eb63a5306fb7ee8520f0810acb960167772f7d964d81b198d80a02f91c4719828ab3732b7c228b3e22d88a8180" - }, - { - "address": "e10A8Cc6c22CDc320c67BD600a1d8a0a46D7f400", - "blsPublicKey": "bfce6153e2c2dabc724d9ccf5cad8916753dce1a495a29053ff7e5b74b0eace4889d5fd2d5859400d82b6bf29cecc9006b6e37152cb1f4f72e7d0c0897439f4ef886e26b4345d2f3e73bcf08d47f02c02976730620d7f844313c099894176980", - "blsPop": "c636f7de65c4846b56381933f255bd3bf2df8594c4bb5efde571df36d5fa09eac71992780e7a7f7573b2dd23469a6a00" - }, - - { - "address": "e3020350aceeA29B783e0C947Ae001692B8F6248", - "blsPublicKey": "d56a6034613c0db14cad99e0d2dc3a2482ff8167a032218ac10508bb04fb8ef91d40a6ef0731f1e162761f09be237800363199f518a1bad98f9f2d179d2028137f9a86588c5cd91534a53d4edcc718b40aab61343571636d052eb7b288578c80", - "blsPop": "3988cfe70f34d8c7823dee13e76ac2efdb83602d5d17c4689f076a9373e55f71a80599cc622216461a7a009d2e141500" - }, - { - "address": "b952930a3656a9cbab21df5919f94c61a495bf79", - "blsPublicKey": "25138a99de6619b2ad03707f847ac0f5d79b0fba2c67a02f5430a57c7a651d6cd63988cb91aa331acd8b7221a41fc4007be73ad86365de5029c22186d2c90a864fd3d386cc074b25f33b4e5f17839d2780b62390f1fe63ec690c1022c039f500", - "blsPop": "0d84d1b7adf26c6d30b31e22671e51a11709685e714836cc113dabc26e9d8fe4f5a07990cfd7695115cbede03a84eb00" - }, - { - "address": "2289a63b4b4700eEECA35323Ea51785f366dd705", - "blsPublicKey": "c1e12e9c0b26d73c27dd5f60f08aa15c952afaa395dbc8b4cb99453bbf3f14ede8a9fc579f64500497344cb3637aa900ac8618d237580558d9ab5b042ac411fd121713744378c9f4d897907f09a71af9331bfecb3853e3f0577be558c9019881", - "blsPop": "2a16befec80fee3bf940965ab5670ebe13c564d9b007914bc16b5de89e7787a680627a93b9ecbf927ead2b1cd45f1480" - }, - { - "address": "0223E40d1f93A6Fe5BEf63605992aDA10740E13B", - "blsPublicKey": "c8e6cf45b640fa91385b4f7e891fe68e5ef6847d032d6ee1b52eef0ff577ad796b881537f94adcbd1b52ba3e0e5d7e014e97406029095598a373fd6d9b6c7754aa87b87560e363faee89c11482cae4a063d7cbe65747f2b095cd2f6688a8bd00", - "blsPop": "6c4c6e5bf183fa84815c84d37f804db9c1c51fe9c77aa725d686f2808c31ff51eebf8ba5470609ae46da3a2f0246c100" - }, - { - "address": "0610b8B4E6f5C3241D53eD3374DdcA8969cD053c", - "blsPublicKey": "08fb22b9fe04caf62059216dfa1d2274ade1df9e8dc0b3c37c2f04a8b3d30a73f8b7ddd873d08c9b9302b936d303380147ce0e19c4600b780a1814730462147fb8280fbd7fe0aa7290d325a2b7b5092e05c037664a0aaea127b0d95fd13e3d81", - "blsPop": "fee988a71b813aafa1fe0e692e0197df3b9946e3a59dddf46944a178249b1c0a981b1e264e3e7f93ef24b8727ac03181" - }, - { - "address": "63b4b616c5345e3DcC9e21dB69297e2129447f4e", - "blsPublicKey": "68dd5abe43baf4f4817a49b094c0bb19ed4971c49a6f91863163f655b6f312d80b7c7843b4cb7a27f7e54d48c41c7a01c5e22e1b0e38a5dbb03dfee76076a9af56146359add6003410005332417f6b65db718acce693cfa21a8fd92f6ad72800", - "blsPop": "a494765b096110901eb3913b433e865e72766183def25a220d6d4c1e26d296eff94a97fb3c1efd35aa70206814f0bf00" - }, - { - "address": "c9A7781729f95b88239c3BFc91fb52f92B44a116", - "blsPublicKey": "91785b64cfd3ac6025b6b536499ac63868344b8f86660ed73b574b000477807d53dacf1d9da258ee1b113485a01579001c5a510dd3b3c5ff1f417c4d97faf997aecedf7602bd96155f8396f5c9fa53d2c601b0de0241fff49939b8a97ce59f81", - "blsPop": "1457b0a74938bc535d310352dec6fe4459143bacaaa6bc198020859af7edcec9b2f9eade86ea1f27a287023c4647b280" - }, - { - "address": "56259f876eB6a7264D9f1a59952bAAD599fF9640", - "blsPublicKey": "00d869e78871139e8a5ff6d590593d94ea39ea73e87ac8d901f0f524372b93752a488b34e05afe05ab53b1c1b5b9a50040341dc01361110551358c9e982f30755e19ec2ad1c1a40afba9998f763599149b976caaded14c1793fe8c469b17c900", - "blsPop": "fc9193e1d8c07c9d5a25cd483e4397f0ef80a52a78e585f04bfebb2275f60975f02f314a3d81d5e539d7b83ccf2daa80" - }, - { - "address": "F139e74aDEC329E715AB49a68c5548A00e40CBc2", - "blsPublicKey": "e87f2bfc49c076239d7522280098c9c4808524c67f3891608c42a510340d64c7e3c1c074c34050007837c13536ee4001108efc87fb2eb8c3236a738122ec086a7b8e6857e82454ff6284a81bf0362424ba96be762d4c06e6aa1b59f20c870780", - "blsPop": "7ae5fe658b4bb7b3aab3868a1504bd272a0b87689c895bce63d791d03eb0aae2fae14d2814785351bad72500d2320600" - }, - { - "address": "33657019D60A0A41f1B9970bD4B28A3A83DBeafc", - "blsPublicKey": "8bd2cb218f465c82702aba73a061227cd83dd8e3115ae592811a4d9a8236e3cb99cfe81b2e22e3620635d42f63b7db00cd546bdf9fad7b49d0b4686962c8e0f4544c8df9f41d30d7d489c86745ef9b61a7dfb498f7554eeaf7e24654e5b2e080", - "blsPop": "41a0094d8e94f622043fa6fd3eed9c7ca83ce3ab2d5cedd48980b7c059a02011eb4c3f2983ac9f42d406fe1a78d23d00" - }, - { - "address": "0F5640bd556B0BE19262D1817B213DDB3424d91d", - "blsPublicKey": "2a5d5145b7a8100575e96cadf2513e7e64dc1354bd891a24f985c2574c9f5f136c6837eab290543d769227785520970133022637837b6e711918f3d2e98291bf3b518247b54e925a0cd080d517731b2725be888fca298ae9ec6f5d2c19146b01", - "blsPop": "ebf73526d3103e85e37316af3b6905ee68f692ccefff0a48d0e17b5a850baa9f444815a4da7a78535c0d4a18c4869b00" - }, - { - "address": "ed8bf82d2e579ff6363aef139f8b147a0105f17e", - "blsPublicKey": "9cedde7d49e2e115896b789ece09a4e8816fae153de891774f0f716a3088e01754498f8ab82d3a4ef5d53dbe17338f0089d1de1eb60bfe3ec2b9701cd882b1c174bdcfaac2225f57481676bd3ee845825be823b9f9317e407b015159b9ce7e80", - "blsPop": "6e1b5dfb7a1ea330a8ece9708bd83219c5d44186f58423991ee1a9951f98c8ef0a8e844169217871cfe6ebe188c2bb80" - }, - { - "address": "d8C68eBeCb6F074ac5C4FB66a690AC0Ad38a5a3c", - "blsPublicKey": "9124b91b223bf9bcb33f75ab8fad0180fdc57536d34349945b80458abc8e59cb06005fabea656b2cd0dc74c0d06160019706965ec3ee0d3b9dd76eb9d39158bd512fe7384bb9e139bc6391d5f7b969397bd85a91bb91670880d861e8fcbd0700", - "blsPop": "589d9703772e103b414b96ad2b39946ebbd671dcb86cffc6cd7eee70991f005ef5dc31f422c5be9f525d940e4fdb5b80" - }, - { - "address": "c6f916aD6E360651Bb95f8e67C1C28805745d084", - "blsPublicKey": "338fa194daae9ba1245931653fa349ce85d37e2f42f871c6b67397401e190b497d15ff23e8f6e9d8637f84fc2dd4640066fee692f5d38208233e7570c3ed49a4ba032d79c7a974883fa5b5c2a113259b924a346bc4edaf717b3d272ceb152980", - "blsPop": "fde95baada162d51e09dde8554ed15ee745759ab1a3c9ec3f6eefdba23b8eaad206283b40a76ea7e9317894bd6641e81" - }, - { - "address": "3ed95D6D4Ce36Ea7B349cD401e324316D956331a", - "blsPublicKey": "6150a62f3bae3a35a639d66dc37ffbc979dda85d6f5c278a5e3a563ed865018c86563be9b878261ef8d34edd3c313500a4f170e22f386674d538b9e15930f39216a38c2a0b60380a140e5897f42d37077784cd0f1a93746e4da42a5da8de1081", - "blsPop": "db8082ee5e6675f9a915decc718f69407da0173d9b1e8696a876043e2b237b6788dc9bb1fb2eae3f46ef3d7844751581" - }, - { - "address": "4A03C4c2E101AC4612d89b79f61c9C5BDd51929D", - "blsPublicKey": "5fd1581e41fa22e7ea0d3ee0674e80e2168fdb42c1aaa3eb8aa395fdde11de5ca98ee71c50b365ef6ad9850bacf7ab011eb446da79efba3ae91fe1f7d9274dacda39b0b3bfaec7d7904eac59d72683c52b6ea091ca1374d8b744fd1d595c5700", - "blsPop": "7e7267713730539c9f67e926b4daa7240e3d8a203d6254f9ef256bed9d4afac9dda11123dd1f1ba72cf2ab123d6c4481" - }, - { - "address": "DD0f3F7beb37fe9D4496F8098446B65DDFB1Fa02", - "blsPublicKey": "e04a671c7f9af919093a9c7aaf5c3d04eff31189d65f5a2aef8a08119ed1c150464c40085bfe2fc1b598fc2ebb095101d0103b995e3a762a9063d823ef6686422caa5a390f9cef5ee6c4b911fd2a818f43fa47ab4d21b01cc7b071b517438d81", - "blsPop": "a419e142a4e1f1f699fbf8f8dcc4718afebab936816ace8374c72e996f873d4180fad6528b65a3f007654f18f10b5d00" - }, - { - "address": "642CBE89A58909BA712dD11ed4C4b2359bd8C85d", - "blsPublicKey": "14cfe4d455820e0b9189ccb32b565b90d414ed7d315d3e61141f085b6aaea34b0c90d1f502f544408e7ed0573e1d1701d38063b239cf847018daa41b7ef75b4458d2fa23e459e9e8039668aca6bc70df1051a6466a5a5bc636e68bc8e2380a80", - "blsPop": "52a7e4854eacf7842224530c2d5338fc31c12a3996134c69e81079627d7c952e962827a8d863ec2bb88fa02a41100200" - }, - { - "address": "FFbCF262C1d5c4392ef469BA79f2CD195d2AffDa", - "blsPublicKey": "45bab7cfb2814e1e3e1a40779219bb48c5d51419ce4c27359d0dfea9fbf1d193ca1cf07934ebf3d6699093387d0e0f000dc5fd2058e7ac50e67c26e5172567c2e7ba9fefa6376e44de800c8955cb330df27476d8ba9c8ec06bba46fddeb95e81", - "blsPop": "48ee6eb577379aa76f34570e6d12f225bfa299d297f9631900bf0d3d2d9bf80915c2ed3cb38c5f75f1893e5c7d168801" - }, - { - "address": "68e0104fD2B5A2c93E97C2bA172C4D2A4223f76f", - "blsPublicKey": "a9fc64c64c039cbd8b23c10c706e51e0013289201111cf8c50e22781161df397fa9c1b91dbab44969aa4f8819f222e01bab90190bebfaecff7076de325dae8080bfe921fbb4ca474d45126fe5ae699dadea98a5255c048b955ab9ba1de8f4c01", - "blsPop": "3b4374544c02f51c5acbde67f407b17f8b5513ab5286b8e8213ba56adb510557f54626009d6e68f8f0505384c64a7d01" - }, - { - "address": "5cAB520442de9baBC290B25E5e2e6A1194Ec6707", - "blsPublicKey": "aa5729ac27a01f26924e863eea7d7b49e4f8ccb15c758ea5ac4d19691a8df31f70138e7f3011fc1e53d52d7063dd8d01a9b3800a66914956769a13ff8d7960725bf1b9073052f3ff85e57b34165702baede05d4e807bfb565a38c24e3542c780", - "blsPop": "629e6b0901b08231287b3bfd0244f9730567d18e675c02dfd4a6c42083d32050b03c88437802a74d66912089d66e7a01" - }, - { - "address": "Bc6963fc0e2f5547bA949ed39e80b8388321104f", - "blsPublicKey": "14dafe41c0d96b22188f0cf6cb99274e09d8ed0546bb57b28a3590449726aedf809c049663a2fe4e40b91830ac864d006a9c5b41cbddeabeef99cfddf6c298de0d482b6e945993241d8987f7fac004fe159f2206060b69d1f8f7f67f63f26280", - "blsPop": "1eb62a80cd53de8e1103f9f3f809e4ed6b5774be448debad52f04cea649c77a18e795e18f6e5ecc89b1d7d0e949b1e81" - }, - { - "address": "43882141555003B3e71110f567373b59Ac4cb0BD", - "blsPublicKey": "878790bb38b1d31707aa37b5af439d64d4a29ea64418b7c01139a26e4f297da6c61a806361e6fee8e40556500c8a6000183b2a42c54d714a143fe12492081f373e3e27e3921adeb276a8daac8b87a534c0fa1d45195d8a35cbda27f883128680", - "blsPop": "8adbdb18b1996f0d156ba332c7cc5cd7a22f701f92cb6102fe81a1f353c24757d2fa3181fea45d0309a39357bd158601" - }, - { - "address": "48cedc58b10af13d688631bc3cb78a05b8a6e56a", - "blsPublicKey": "7983d25868e1915ca8c20603bb70475b398acb04fef221106475f0fc25a3df25d181050214da347bfcd8f8292e5257014ba77cf67ee5f42202257317808f126930b4eaaf4bec801c4465ced54bd78331f8d3dadfdf2f91de294836c13e946001", - "blsPop": "2b0cbe1b28d6a36828022b21807fe74fb64b6de77325719347cbff51b256ae91eb96ad9339eb68b6a43b522613049200" - }, - { - "address": "65698c9ec5Af10345cd1e39472D60FB6133bad6F", - "blsPublicKey": "c700f20fab4ebb8ba2f47adf177e3a9dbbfb8d999acbaf0055cc540758f8c00c4564813d910e7be02e4ceaa97fb88000b3e8e6fb4308fb943fa0a3d8ee32c3a16e67eae0817370de54bec1e13193cc845cedb70e48171e097550475684cc6600", - "blsPop": "3c7dd9c5298690b795c30da0a78435a17717c88b8adea527f74335d2cdafa993153837f4b6a5beaedb4aa25bb20aa700" - }, - { - "address": "D507309fd69635aa37810A65A4dA27Ec47a1BA05", - "blsPublicKey": "3a3857a5e4a709e1891a13797d55c1698f931755492099926314feec955da31fcea8a8c8e52ce2efd74008f32dbc1c00c1b3d36c1f3097d806f1687eff4a979ff967a8233f923a1af6a3104c12d9d44388bece91a248bd86f253e709cea7a380", - "blsPop": "25544d8e28279a43483cd8b45386e4ab071618e352172a60c85c3e65bd5d9efc46bc490eb36707886a7356ac864a1981" - }, - { - "address": "C46Dc0741FF61af883E284daEA062ae7382E7091", - "blsPublicKey": "d8704fbf6968ffd9f39f78173726dfebbaaffebd8a33dfe29a72b9a64204debf2016ca94cbecb1b84cab9d5cc168f70082530b8cfab0225a37c8cc3044c288ab0fea2f484b56a33fe6c92d6c50f254e6b1689ac6bb1429cc36a0a7dfa85cf880", - "blsPop": "d0feceb95fb140f985996bcbfb2db22f18f5ba7b02b5b0f7167d02f6ab517080a4db6c4108f46bca1417d32f50dad100" - }, - { - "address": "198958f0b860AB0E3937F468FE366AAc9EEbaD2e", - "blsPublicKey": "89bc906b5ea07752b1981558fd5d329f6d428bc14dfde022745303eae0077612b9c473cd66e4d91778282ec98bbd74001b61cd71448750df642fb580ce81a62ff2f5ab4378528ccd65acff67ac2175678f598529c768247c77938ca2d529aa01", - "blsPop": "2a3a0e6a10d83a353eb25d6cb56b6693150e0d8645ed2df72e77676bc430ae39e825dd1467025c9f08a1eae142685281" - }, - { - "address": "0ec5a403212d732d8d7ced050e9510f6327453c6", - "blsPublicKey": "fb9de050c059a11175be23daeef1bfc374a688d8fd776e7d2dc81fe301068a3af03ad522bd915a154dc8b5b8e12d38003f17bf9f3001e8bc682e38cfc93c6901417afe1ddbfe11b04f42ca4f321f7ba73fa98f0e8c8d75781b14c0dea847a500", - "blsPop": "39896a46d6bb64549527a34474aba7b852954bc5bfb8b69e3593bfef083974a75d47ca4a92296774935ccb4feaac9a81" - }, - { - "address": "464CCE7999B3D90a8F1fFaf94A71FBDeA1E65435", - "blsPublicKey": "bef17561ef747e0f11fd339987a9813fa8ac1cbbd6457ab8fae4841f2217de019de7caf421631372b7eec730d9210d0128e6c560948c19ab6141d6699e0283a5b98abb8266d731f2b6435a07b44360a3f5622cff59103ec95938ab74fe1d8f01", - "blsPop": "02fedb06b8477cdc8b6d4f556f85cae99c483eefeb01eed7808decc05c1d55405e7a42c299e89d6249cfbd3122d66881" - }, - { - "address": "097095B8cF5cabF0c39E548D8DF55DD635D84D07", - "blsPublicKey": "a47fd022dda04d8dd36e0a8127be68736e47e490b946d2d88a9fdcca0a5114a930db2319e7e9f378d1b81da865d38b01a063e9994e620483b08047da39ee2fba35f66df5734e1545d297be0225ddfda34e494c1f09825eed303d166a8b702f01", - "blsPop": "afe49aecae6f431e88469fa5e185f4e34d3c6b02f41487927690ef4f2d877349b6dcdd62dff31c508a291b7099a23880" - }, - { - "address": "AA937dA037E617e868795EAC1dcD43C663014D32", - "blsPublicKey": "5966b41d69c0e94e202f65823338c3ee0357b024a6ef625765bcf3c20e1786258a18221e0b9a34b43380e06984d92f0183d0f86d0dfe0cac237ee38b28876dada3ae9d1a7c1e6627c3b524d0e5d4270bbe159661622821412b3c1162881ead80", - "blsPop": "ff11ad6c1336adb225fb1319d8372cb5408956dd8cd1272f0210ef9ff8120a3ceeca92b21723375c75e5347935225b80" - }, - { - "address": "f11073eb2D259b90A91954caE30D0E6E9ecC7F11", - "blsPublicKey": "8fad3c2111494834f30e6d8a3368f2aa156c991fa4b9d55c31da88310a61248305697ad5e885404bc474419383de4f006c89c84955321716f6ceb4d5db433fcabe843d566a5e9526d29c58b38fda9ff2a13f7841f25cda8ff091c965bdf91780", - "blsPop": "c932f10076512167e286373ac63e4a7aa60793b4a029d68a2972cd65017e145b521d06667e64ed720f041f8a3b0ae680" - }, - { - "address": "5b55452Bdba5971D606F47647bd383f3C3fa7285", - "blsPublicKey": "7f9df4fdb96e20e0a480a62c48896646d96982d7fccccdf70c61f2f52ab4ea2901b5ef468203f39d9d8325843ada0d00e9562c64f79ec16d69b5921ad36306ae9ae2ab97806b354af8cb63722a96aed5fa0542fff58d2e41f6aee3cb641f7781", - "blsPop": "96394cfa698e6f8fdd6b66f47c99becf374c3c4daae50a48ddb94ce15cee803b12f985684d6bc759c2549b700f343600" - }, - { - "address": "439d5E4D7578ECc9eFa52A8Cf1887b11FD0FB900", - "blsPublicKey": "9cc39207797e5c37f6336c4444cf275d0afd43a9b257a08086f15867886833744c9b5753fcff76fce3790d7f25a45e004af9831464bf43e39634ecfce8da4641da78ad4ba20e540c007dbc19e391ae69cfb7809b2d20627d553a16d7d71b5a80", - "blsPop": "ca89ff2d6ebe328f9644dfbfc5f1c4c9276db8e5c37336e89d21a576074dfa92d1115d5defa2d7d4af0bf9c03a885181" - }, - { - "address": "92f628b0157D47C992F5C69dBBD038b110E27826", - "blsPublicKey": "e6631bd0b82c41327b582d7b239c9893cd1162cae05f360d8808700b38ee0ee965e9bd9246d79e00c234c87aa7699800c73428f7eccd77337bf79bf6b43f48345be265c38d128d2cd7f37167cadb3565d66e6a7f67b12f4bed63e5d507480100", - "blsPop": "ccdf1a5f80759b6748720ae804df42c44fa6438bc8b8129f47f8bb31078a073d7a5959a59b8fc8392f200862378a5d80" - } -] \ No newline at end of file diff --git a/packages/celotool/package.json b/packages/celotool/package.json deleted file mode 100644 index 3958172d9..000000000 --- a/packages/celotool/package.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "name": "@celo/celotool", - "version": "2.0.1", - "description": "Celotool is our hub for all scripts that people need to run within the monorepo", - "main": "index.js", - "author": "Celo", - "license": "Apache-2.0", - "dependencies": { - "@celo/base": "^6.0.0", - "@celo/connect": "^5.1.1", - "@celo/cryptographic-utils": "^5.0.6", - "@celo/contractkit": "^6.0.0", - "@celo/env-tests": "1.0.3", - "@celo/explorer": "^5.0.7", - "@celo/governance": "^5.0.7", - "@celo/network-utils": "^5.0.5", - "@celo/utils": "^5.0.6", - "@ethereumjs/util": "8.0.5", - "@ethereumjs/rlp": "4.0.1", - "@google-cloud/monitoring": "0.7.1", - "@google-cloud/pubsub": "^0.28.1", - "@google-cloud/secret-manager": "3.0.0", - "@google-cloud/storage": "^2.4.3", - "bignumber.js": "^9.0.0", - "bip32": "3.1.0", - "bip39": "https://github.com/bitcoinjs/bip39#d8ea080a18b40f301d4e2219a2991cd2417e83c2", - "bunyan": "1.8.12", - "bunyan-gke-stackdriver": "0.1.2", - "compare-versions": "^3.5.1", - "dotenv": "^16.0.3", - "ecurve": "^1.0.6", - "ethereum-cryptography": "1.2.0", - "generate-password": "^1.5.1", - "js-yaml": "^3.13.1", - "lodash": "^4.17.21", - "node-fetch": "^2.6.7", - "prompts": "1.2.0", - "read-last-lines": "^1.7.2", - "sleep-promise": "^8.0.1", - "string-hash": "^1.1.3", - "tiny-secp256k1": "2.2.1", - "web3": "1.10.0", - "web3-eth-admin": "1.0.0-beta.55", - "yargs": "17.7.2" - }, - "devDependencies": { - "@celo/dev-utils": "0.0.1", - "@celo/protocol": "1.0.2", - "@types/bunyan": "1.8.8", - "@types/chai": "^4.1.3", - "@types/dotenv": "^8.2.0", - "@types/mocha": "^10.0.1", - "@types/node-fetch": "^2.5.7", - "@types/prompts": "^1.1.1", - "@types/string-hash": "^1.1.1", - "@types/yargs": "^13.0.2", - "chai": "^4.3.7", - "mocha": "^10.2.0", - "web3-core": "1.10.0" - }, - "scripts": { - "cli": "TS_NODE_FILES=true ts-node -r tsconfig-paths/register src/cli.ts", - "lint": "tslint -c tslint.json --project tsconfig.json", - "build": "tsc -b ." - }, - "private": true -} diff --git a/packages/celotool/requirements.txt b/packages/celotool/requirements.txt deleted file mode 100644 index e5ed2a091..000000000 --- a/packages/celotool/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -docopt diff --git a/packages/celotool/src/cli.ts b/packages/celotool/src/cli.ts deleted file mode 100755 index c74f74af9..000000000 --- a/packages/celotool/src/cli.ts +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env yarn run ts-node -r tsconfig-paths/register --cwd ../celotool -import yargs from 'yargs' - -// tslint:disable-next-line: no-unused-expression -yargs - .scriptName('celotooljs') - .option('verbose', { - type: 'boolean', - description: - 'Whether to show a bunch of debugging output like stdout and stderr of shell commands', - default: false, - }) - .option('yesreally', { - type: 'boolean', - description: 'Reply "yes" to prompts about changing staging/production (be careful!)', - default: false, - }) - .option('helmdryrun', { - type: 'boolean', - description: 'Simulate the Helm deployment. Other deployment operations can be executed', - default: false, - }) - .middleware([ - (argv: any) => { - process.env.CELOTOOL_VERBOSE = argv.verbose - process.env.CELOTOOL_CONFIRMED = argv.yesreally - process.env.CELOTOOL_HELM_DRY_RUN = argv.helmdryrun - }, - ]) - .commandDir('cmds', { extensions: ['ts'] }) - .demandCommand() - .help() - .wrap(yargs.terminalWidth()).argv diff --git a/packages/celotool/src/cmds/account.ts b/packages/celotool/src/cmds/account.ts deleted file mode 100644 index b77e76a30..000000000 --- a/packages/celotool/src/cmds/account.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { addCeloEnvMiddleware, CeloEnvArgv } from 'src/lib/env-utils' -import yargs from 'yargs' - -export const command = 'account ' - -export const describe = 'commands for inviting, fauceting, looking up accounts and users' - -export type AccountArgv = CeloEnvArgv - -export const builder = (argv: yargs.Argv) => { - return addCeloEnvMiddleware(argv).commandDir('account', { extensions: ['ts'] }) -} -export const handler = () => { - // empty -} diff --git a/packages/celotool/src/cmds/account/faucet.ts b/packages/celotool/src/cmds/account/faucet.ts deleted file mode 100644 index f22b60676..000000000 --- a/packages/celotool/src/cmds/account/faucet.ts +++ /dev/null @@ -1,188 +0,0 @@ -/* tslint:disable no-console */ -import { newKitFromWeb3 } from '@celo/contractkit' -import { celoTokenInfos, CeloTokenType, Token } from '@celo/contractkit/lib/celo-tokens' -import { concurrentMap, sleep } from '@celo/utils/lib/async' -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { execCmd } from 'src/lib/cmd-utils' -import { convertToContractDecimals } from 'src/lib/contract-utils' -import { getBlockscoutUrl } from 'src/lib/endpoints' -import { envVar, fetchEnv } from 'src/lib/env-utils' -import { portForwardAnd } from 'src/lib/port_forward' -import { validateAccountAddress } from 'src/lib/utils' -import Web3 from 'web3' -import yargs from 'yargs' -import { AccountArgv } from '../account' - -export const command = 'faucet' - -export const describe = 'command for fauceting an address with gold and/or dollars' - -interface FaucetArgv extends AccountArgv { - account: string - tokenParams: TokenParams[] - checkZero: boolean - checkDeployed: boolean - blockscout: boolean -} -interface TokenParams { - token: CeloTokenType - amount: number -} - -export const builder = (argv: yargs.Argv) => { - return argv - .option('account', { - type: 'string', - description: 'Account(s) to faucet', - demand: 'Please specify comma-separated accounts to faucet', - coerce: (addresses) => { - return addresses.split(',').map((a: string) => { - if (!a.startsWith('0x')) { - a = `0x${a}` - } - if (!validateAccountAddress(a)) { - throw Error(`Receiver Address is invalid: "${a}"`) - } - return a - }) - }, - }) - .array('tokenParams') - .option('tokenParams', { - type: 'string', - description: ' pair to faucet', - demand: - 'Please specify stableToken,amount pairs to faucet (ex: --tokenParams CELO,3 cUSD,10 cEUR,5)', - coerce: (pairs) => { - // Ensure that pairs are formatted properly and use possible tokenParams - const validCeloTokens = Object.values(celoTokenInfos).map((tokenInfo) => { - return tokenInfo.symbol - }) - return pairs.map((pair: string) => { - const [token, amount] = pair.split(',') - if (token === undefined || amount === undefined) { - throw Error(`Format of tokenParams should be: --tokenParams tokenName,amount`) - } - // Note: this does not check if token has been deployed on network - if (!validCeloTokens.includes(token as CeloTokenType)) { - throw Error(`Invalid token '${token}', must be one of: ${validCeloTokens}.`) - } - if (!(amount && /^\d+$/.test(amount))) { - throw Error(`Invalid amount '${amount}', must consist of only numbers.`) - } - return { - token: token as CeloTokenType, - amount: Number(amount), - } - }) - }, - }) - .option('checkZero', { - type: 'boolean', - description: 'Check that the balance is zero before fauceting', - default: false, - }) - .option('checkDeployed', { - type: 'boolean', - description: 'Check that token is deployed on current network', - default: false, - }) - .option('blockscout', { - type: 'boolean', - description: 'Open in blockscout afterwards', - default: false, - }) -} - -export const handler = async (argv: FaucetArgv) => { - await switchToClusterFromEnv(argv.celoEnv) - const addresses = argv.account - - const cb = async () => { - const web3 = new Web3('http://localhost:8545') - const kit = newKitFromWeb3(web3) - const account = (await kit.connection.getAccounts())[0] - console.log(`Using account: ${account}`) - kit.connection.defaultAccount = account - - // Check that input token has been deployed to this network - if (argv.checkDeployed) { - const deployedCeloTokens = Object.values(await kit.celoTokens.validCeloTokenInfos()).map( - (tokenInfo) => { - return tokenInfo.symbol - } - ) - argv.tokenParams.map((tokenParam) => { - if (!deployedCeloTokens.includes(tokenParam.token)) { - throw Error( - `Invalid token '${tokenParam.token}' (or not yet deployed on ${argv.celoEnv}) must be one of: ${deployedCeloTokens}.` - ) - } - }) - } - - const faucetToken = async (tokenParams: TokenParams) => { - if (!tokenParams.amount) { - return - } - - const tokenWrapper = await kit.celoTokens.getWrapper(tokenParams.token as any) - for (const address of addresses) { - if (argv.checkZero) { - // Throw error if address account balance of this token is not zero - if (!(await tokenWrapper.balanceOf(address)).isZero()) { - throw Error( - `Unable to faucet ${tokenParams.token} to ${address} on ${argv.celoEnv}: --checkZero specified, but balance is non-zero` - ) - } - } - const tokenAmount = await convertToContractDecimals(tokenParams.amount, tokenWrapper) - console.log(`Fauceting ${tokenAmount.toFixed()} of ${tokenParams.token} to ${address}`) - - if (tokenParams.token === Token.CELO) { - // Special handling for reserve transfer - const reserve = await kit.contracts.getReserve() - if (await reserve.isSpender(account)) { - await reserve.transferGold(address, tokenAmount.toFixed()).sendAndWaitForReceipt() - return - } - } - await tokenWrapper.transfer(address, tokenAmount.toFixed()).sendAndWaitForReceipt() - console.log(`Successfully fauceted ${tokenParams.token}`) - } - } - // Ensure all faucets attempts are independent of failures and report failures. - const failures = ( - await concurrentMap( - Math.min(argv.tokenParams.length, 10), - argv.tokenParams, - async (tokenParams) => { - return faucetToken(tokenParams) - .then(() => null) - .catch((err) => `Token ${tokenParams.token}: (${err})`) - } - ) - ).filter((x) => x != null) - if (failures.length) { - console.error(`Error(s) fauceting: \n${failures.join('\n')}`) - return - } - - if (argv.blockscout) { - // Open addresses in blockscout - await sleep(1 + parseInt(fetchEnv(envVar.BLOCK_TIME), 10) * 1000) - const blockscoutUrl = getBlockscoutUrl(argv.celoEnv) - for (const address of addresses) { - await execCmd(`open ${blockscoutUrl}/address/${address}`) - } - } - } - - try { - await portForwardAnd(argv.celoEnv, cb) - } catch (error) { - console.error(`Unable to faucet ${argv.account} on ${argv.celoEnv}`) - console.error(error) - process.exit(1) - } -} diff --git a/packages/celotool/src/cmds/account/list.ts b/packages/celotool/src/cmds/account/list.ts deleted file mode 100644 index ce57a4fe5..000000000 --- a/packages/celotool/src/cmds/account/list.ts +++ /dev/null @@ -1,145 +0,0 @@ -/* tslint:disable no-console */ -import fetch from 'node-fetch' -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { getBlockscoutUrl } from 'src/lib/endpoints' -import { Argv } from 'yargs' -import { AccountArgv } from '../account' - -export const command = 'list' -export const describe = 'Command for listing users' - -type ListArgv = AccountArgv - -// Known accounts for argentinaproduction -const knownAccounts = new Map([ - ['0xd4662aed4aa8719cd7dd9bc01034627951184a64', "Will's Phone number +5491126196048"], - ['0x5feb9f304d8309f4802dda947eac50558a7e0c62', "Anca's Phone number +5491126033185 "], - ['0x2e7e480e7d6a2577a72a869788dc2acd7b069e9d', "Nicolas's Phone number +5491150466926"], - ['0x3cb712ff0114ca421d2aefb9e4fdbe8e78be0936', "Vanessa's Phone number +5491157641239"], - ['0x1f2b673387a470c9b45397f7cd9f81eeff37af3a', "Jason's Phone number +5491136815320"], -]) - -export const builder = (yargs: Argv) => { - return yargs -} - -export const handler = async (argv: ListArgv) => { - const domain = getBlockscoutUrl(argv.celoEnv) - const listUsersUrl = `${domain}/api?module=account&action=tokentx&address=0x0000000000000000000000000000000000000abe` - - await switchToClusterFromEnv(argv.celoEnv, false, true) - - console.log(`Getting list of users for "${argv.celoEnv}" environment`) - const resp = await fetch(listUsersUrl) - const jsonResp = await resp.json() - await handleListOfUsers(domain, jsonResp, process.env.CELOTOOL_VERBOSE === 'true') -} - -async function handleListOfUsers(domain: string, json: any, verboseMode: boolean) { - if (verboseMode) { - console.log('verbose mode enabled') - } - const transactionUrlPrefix = `${domain}/api?module=account&action=tokentx&address=` - const users = new Set() - for (const object of json.result) { - users.add(object.from) - } - - console.log(`Num of users: ${users.size}`) - const usersArray = Array.from(users.values()) - const usersAndTransactions = new Array(usersArray.length) - - console.debug('Getting transactions for all the users, this will take time...') - - const transactions = await Promise.all( - usersArray.map((address: string) => - getNonverificationTransactions(transactionUrlPrefix + address) - ) - ) - for (let i = 0; i < usersArray.length; i++) { - const address = usersArray[i] - const numRealTransactions = transactions[i].length - const latestTransactionTimestamp = getLatestTransactionTimestamp(transactions[i]) - usersAndTransactions[i] = { address, numRealTransactions, latestTransactionTimestamp } - if (verboseMode) { - console.debug( - `Address ${i + 1}/${ - usersArray.length - }: ${address}, non-verification transactions: ${numRealTransactions}` - ) - const transactionUrl = transactionUrlPrefix + address - console.debug(`Transaction address: ${transactionUrl}`) - } - } - - console.debug('Sorting users in the decreasing order of transactions...') - // Sort in decreasing order of the number of transactions. For users with same number - // of transactions, put the user who made the latest transaction first. - usersAndTransactions - .sort((a: any, b: any) => { - if (a.numRealTransactions !== b.numRealTransactions) { - return a.numRealTransactions - b.numRealTransactions - } - return a.latestTransactionTimestamp - b.latestTransactionTimestamp - }) - .reverse() - - for (const entry of usersAndTransactions) { - const address = entry.address - const numRealTransactions = entry.numRealTransactions - const latestTransactionTimestampInSeconds = entry.latestTransactionTimestamp - const lastTransactionHumanReadableTime = - latestTransactionTimestampInSeconds > 0 - ? new Date(latestTransactionTimestampInSeconds * 1000).toLocaleString() - : 'Not applicable' - let infoString = - `Address: ${address}\t` + - `non-verification transactions: ${numRealTransactions}\t` + - `last transaction on: ${lastTransactionHumanReadableTime}` - - if (knownAccounts.has(address)) { - infoString = `${infoString} (${knownAccounts.get(address)}` - } - console.log(infoString) - } -} - -async function getNonverificationTransactions(transactionUrl: string) { - let jsonResp: any - - // Try thrice before giving up. - for (let i = 0; i < 3; i++) { - try { - const resp = await fetch(transactionUrl) - jsonResp = await resp.json() - } catch (e) { - await sleep(Math.random() * 5000) - } - } - - if (jsonResp === null) { - console.error(`Failed to get valid response for ${transactionUrl}`) - return [] - } - - if (jsonResp == null || jsonResp.result == null) { - return [] - } - return jsonResp.result.filter( - (transaction: any) => transaction.to !== '0x0000000000000000000000000000000000000abe' - ) -} - -const getLatestTransactionTimestamp = (transactions: any[]): number => { - let maxValue = -1 - for (const transaction of transactions) { - if (parseInt(transaction.timeStamp, 10) > maxValue) { - maxValue = transaction.timeStamp - } - } - return maxValue -} - -function sleep(milliseconds: number) { - return new Promise((resolve) => setTimeout(resolve, milliseconds)) -} diff --git a/packages/celotool/src/cmds/account/revoke.ts b/packages/celotool/src/cmds/account/revoke.ts deleted file mode 100644 index 773299b91..000000000 --- a/packages/celotool/src/cmds/account/revoke.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { downloadArtifacts } from 'src/lib/artifacts' -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { execCmd } from 'src/lib/cmd-utils' -import { portForwardAnd } from 'src/lib/port_forward' -import yargs from 'yargs' -import { AccountArgv } from '../account' -export const command = 'revoke' - -export const describe = 'command for revoking verification of a phone number' - -interface RevokeArgv extends AccountArgv { - phone: string -} - -export const builder = (argv: yargs.Argv) => { - return argv.option('phone', { - type: 'string', - description: 'Phone number to revoke verification', - demand: 'Please specify phone number to revoke verification', - }) -} - -export const handler = async (argv: RevokeArgv) => { - await switchToClusterFromEnv(argv.celoEnv, true, false) - console.info(`Sending invitation code to ${argv.phone}`) - const cb = async () => { - await execCmd(`yarn --cwd ../protocol run revoke -n ${argv.celoEnv} -p ${argv.phone}`) - } - try { - await downloadArtifacts(argv.celoEnv) - await portForwardAnd(argv.celoEnv, cb) - } catch (error) { - console.error(`Unable to revoke verification for ${argv.phone}`) - console.error(error) - process.exit(1) - } -} diff --git a/packages/celotool/src/cmds/account/scripts/faucet-multiple.sh b/packages/celotool/src/cmds/account/scripts/faucet-multiple.sh deleted file mode 100755 index afd548ebf..000000000 --- a/packages/celotool/src/cmds/account/scripts/faucet-multiple.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -CELO="$(dirname "$0")/../../../../../../.." - -cd $CELO/celo-monorepo && yarn build-sdk $1; - -$CELO/celo-monorepo/packages/celotool/bin/celotooljs.sh port-forward -e $1 & -sleep 5; - -$CELO/celo-monorepo/packages/celotool/bin/celotooljs.sh account faucet-multiple-helper -e $1 --accounts $2 - -killall -9 kubectl; diff --git a/packages/celotool/src/cmds/backup.ts b/packages/celotool/src/cmds/backup.ts deleted file mode 100644 index 99e8a93a4..000000000 --- a/packages/celotool/src/cmds/backup.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { execCmdWithExitOnFailure } from 'src/lib/cmd-utils' -import { addCeloEnvMiddleware, CeloEnvArgv } from 'src/lib/env-utils' -import yargs from 'yargs' - -export const command = 'backup' - -export const describe = "command for backing up a miner's persistent volume (PVC)" - -interface BackupArgv extends CeloEnvArgv { - minername: string -} - -export const builder = (args: yargs.Argv) => { - return addCeloEnvMiddleware(args).option('minername', { - type: 'string', - description: 'Name of the miner node', - demand: 'Please specify the miner node to backup, eg. gethminer1', - }) -} - -export const handler = async (argv: BackupArgv) => { - await switchToClusterFromEnv(argv.celoEnv, false, true) - - const minerName = argv.minername - // In the future, we can make this configurable. - const zone = 'us-west1-a' - const namespace = argv.celoEnv - const pvc = `${namespace}-${minerName}-pvc` - - const getPVCNameCommand = `kubectl get persistentvolumeclaim ${pvc} --namespace ${namespace} -o=jsonpath={.spec.volumeName}` - const pvcId = (await execCmdWithExitOnFailure(getPVCNameCommand))[0] - console.debug(`Persistent Volume Claim is ${pvcId}`) - const getPDNameCommand = `kubectl get persistentvolume ${pvcId} -o=jsonpath={.spec.gcePersistentDisk.pdName}` - const pdId = (await execCmdWithExitOnFailure(getPDNameCommand))[0] - console.debug(`Persistent Disk is ${pdId}`) - - const snapshotName = `snapshot-${namespace}-${minerName}-pvc-${Date.now()}` - const createSnapshotCommand = `gcloud compute disks snapshot ${pdId} --zone ${zone} --snapshot-names ${snapshotName}` - await execCmdWithExitOnFailure(createSnapshotCommand) - const gcloudSnapshotsUrl = 'https://console.cloud.google.com/compute/snapshots' - console.info(`Snapshot \"${snapshotName}\" can be seen at ${gcloudSnapshotsUrl}`) -} diff --git a/packages/celotool/src/cmds/bots.ts b/packages/celotool/src/cmds/bots.ts deleted file mode 100644 index a6855752f..000000000 --- a/packages/celotool/src/cmds/bots.ts +++ /dev/null @@ -1,15 +0,0 @@ -import yargs from 'yargs' - -export const command = 'bots ' - -export const describe = 'various bots we have' - -export type BotsArgv = yargs.Argv - -export const builder = (argv: yargs.Argv) => { - return argv.commandDir('bots', { extensions: ['ts'] }) -} - -export const handler = () => { - // empty -} diff --git a/packages/celotool/src/cmds/bots/auto-vote.ts b/packages/celotool/src/cmds/bots/auto-vote.ts deleted file mode 100644 index 8c96e0e2a..000000000 --- a/packages/celotool/src/cmds/bots/auto-vote.ts +++ /dev/null @@ -1,326 +0,0 @@ -// The purpose of the Voting bot in a testnet is to add incentives for good -// behavior by validators. This introduces some non-validator stakers into the -// network that will judge the validator groups, and vote accordingly. -import { Address, ContractKit, newKitFromWeb3 } from '@celo/contractkit' -import { - ensureLeading0x, - eqAddress, - normalizeAddressWith0x, - NULL_ADDRESS, - privateKeyToAddress, -} from '@celo/utils/lib/address' -import { concurrentMap } from '@celo/utils/lib/async' -import BigNumber from 'bignumber.js' -import { groupBy, mapValues } from 'lodash' -import { envVar, fetchEnv } from 'src/lib/env-utils' -import { AccountType, getPrivateKeysFor } from 'src/lib/generate_utils' -import Web3 from 'web3' -import { Argv } from 'yargs' - -export const command = 'auto-vote' - -export const describe = 'for each of the voting bot accounts, vote for the best groups available' - -interface SimulateVotingArgv { - celoProvider: string - excludedGroups?: string[] -} - -export const builder = (yargs: Argv) => { - return yargs - .option('celoProvider', { - type: 'string', - description: 'The node to use', - default: 'http://localhost:8545', - }) - .option('excludedGroups', { - type: 'string', - description: 'A comma separated list of groups to exclude from voting eligibility', - coerce: (addresses: string) => { - return addresses - .split(',') - .filter((a) => a.length > 0) - .map(normalizeAddressWith0x) - }, - }) -} - -export const handler = async function simulateVoting(argv: SimulateVotingArgv) { - try { - const mnemonic = fetchEnv(envVar.MNEMONIC) - const numBotAccounts = parseInt(fetchEnv(envVar.VOTING_BOTS), 10) - - const excludedGroups: string[] = argv.excludedGroups || [] - - const kit = newKitFromWeb3(new Web3(argv.celoProvider)) - const election = await kit.contracts.getElection() - - const wakeProbability = new BigNumber(fetchEnv(envVar.VOTING_BOT_WAKE_PROBABILITY)) - const baseChangeProbability = new BigNumber(fetchEnv(envVar.VOTING_BOT_CHANGE_BASELINE)) - const exploreProbability = new BigNumber(fetchEnv(envVar.VOTING_BOT_EXPLORE_PROBABILITY)) - const scoreSensitivity = new BigNumber(fetchEnv(envVar.VOTING_BOT_SCORE_SENSITIVITY)) - - const allBotKeys = getPrivateKeysFor(AccountType.VOTING_BOT, mnemonic, numBotAccounts) - await activatePendingVotes(kit, allBotKeys) - - const botKeysVotingThisRound = allBotKeys.filter((_) => - wakeProbability.isGreaterThan(Math.random()) - ) - console.info(`Participating this time: ${botKeysVotingThisRound.length} of ${numBotAccounts}`) - - // If no bots are participating, return early - if (botKeysVotingThisRound.length === 0) { - return - } - - const groupCapacities = await calculateInitialGroupCapacities(kit) - const groupScores = await calculateGroupScores(kit) - const groupWeights = calculateGroupWeights(groupScores, scoreSensitivity) - - const unelectedGroups = Object.keys(groupCapacities).filter((k) => !groupScores.has(k)) - - for (const key of botKeysVotingThisRound) { - const botAccount = ensureLeading0x(privateKeyToAddress(key)) - - kit.connection.addAccount(key) - kit.connection.defaultAccount = botAccount - - console.info(`Voting as: ${botAccount}.`) - try { - // Get current vote for this bot. - // Note: though this returns an array, the bot process only ever chooses one group, - // so this takes a shortcut and only looks at the first in the response - const currentVote = (await election.getVoter(botAccount)).votes[0] - const currentGroup = currentVote ? normalizeAddressWith0x(currentVote.group) : undefined - - // Handle the case where the group the bot is currently voting for does not have a score - if ( - !currentGroup || - shouldChangeVote( - groupScores.get(currentGroup) || new BigNumber(0), - scoreSensitivity, - baseChangeProbability - ) - ) { - // Decide which method of picking a new group, and pick one if there are unelected - // groups with capacity - let randomlySelectedGroup: string = NULL_ADDRESS - if (exploreProbability.isGreaterThan(Math.random())) { - console.info('Vote Method: unweighted random choice of unelected') - randomlySelectedGroup = getUnweightedRandomChoice( - unelectedGroups.filter((k) => - shouldBeConsidered(k, currentGroup, excludedGroups, groupCapacities) - ) - ) - if (randomlySelectedGroup === NULL_ADDRESS) { - console.info('No unelected groups available, falling back to weighted-by-score') - } - } - - // This catches 2 cases in which randomlySelectedGroup is undefined: - // 1. it tried to pick an unelected group, but none were available - // 2. it is not using the "explore" strategy - if (randomlySelectedGroup === NULL_ADDRESS) { - console.info('Vote Method: weighted random choice among those with scores') - randomlySelectedGroup = getWeightedRandomChoice( - groupWeights, - [...groupCapacities.keys()].filter((k) => - shouldBeConsidered(k, currentGroup, excludedGroups, groupCapacities) - ) - ) - } - - if (randomlySelectedGroup === NULL_ADDRESS) { - console.info('Was unable to find an available group to vote for. Skipping this time.') - } else { - await castVote(kit, botAccount, randomlySelectedGroup, groupCapacities) - } - } else { - console.info(`${botAccount} has decided to keep their existing vote`) - } - } catch (error) { - console.error(`Failed to vote as ${botAccount}`) - console.info(error) - } - } - } catch (error) { - console.error(error) - process.exit(1) - } finally { - process.exit(0) - } -} - -async function castVote( - kit: ContractKit, - botAccount: string, - voteForGroup: Address, - groupCapacities: Map -) { - const lockedGold = await kit.contracts.getLockedGold() - const election = await kit.contracts.getElection() - - const lockedGoldAmount = await lockedGold.getAccountTotalLockedGold(botAccount) - if (lockedGoldAmount.isZero()) { - console.info(`No locked gold exists for ${botAccount}, skipping...`) - return - } - - const currentVotes = (await election.getVoter(botAccount)).votes - - // Revoke existing vote(s) if any and update capacity of the group - for (const vote of currentVotes) { - const revokeTxs = await election.revoke(botAccount, vote.group, vote.pending.plus(vote.active)) - await concurrentMap(10, revokeTxs, (tx) => { - return tx.sendAndWaitForReceipt({ from: botAccount }) - }) - const group = normalizeAddressWith0x(vote.group) - const oldCapacity = groupCapacities.get(group)! - groupCapacities.set(group, oldCapacity.plus(vote.pending.plus(vote.active))) - } - - const groupCapacity = groupCapacities.get(voteForGroup)! - const voteAmount = BigNumber.minimum(lockedGoldAmount, groupCapacity) - const voteTx = await election.vote(voteForGroup, BigNumber.minimum(voteAmount)) - await voteTx.sendAndWaitForReceipt({ from: botAccount }) - console.info(`Completed voting as ${botAccount}`) - - groupCapacities.set(voteForGroup, groupCapacity.minus(voteAmount)) -} - -async function calculateInitialGroupCapacities(kit: ContractKit): Promise> { - console.info('Determining which groups have capacity for more votes') - - const validators = await kit.contracts.getValidators() - const election = await kit.contracts.getElection() - - const groupCapacities = new Map() - for (const groupAddress of await validators.getRegisteredValidatorGroupsAddresses()) { - const vgv = await election.getValidatorGroupVotes(groupAddress) - if (vgv.eligible) { - groupCapacities.set(normalizeAddressWith0x(groupAddress), vgv.capacity) - } - } - - return groupCapacities -} - -async function calculateGroupScores(kit: ContractKit): Promise> { - console.info('Calculating weights of groups based on the scores of elected validators') - const election = await kit.contracts.getElection() - const validators = await kit.contracts.getValidators() - - const validatorSigners = await election.getCurrentValidatorSigners() - const validatorAccounts = ( - await concurrentMap(10, validatorSigners, (acc) => { - return validators.getValidatorFromSigner(acc) - }) - ).filter((v) => !!v.affiliation) // Skip unaffiliated - - const validatorsByGroup = groupBy(validatorAccounts, (validator) => - normalizeAddressWith0x(validator.affiliation!) - ) - - const validatorGroupScores = mapValues(validatorsByGroup, (vals) => { - const scoreSum = vals.reduce((a, b) => a.plus(b.score), new BigNumber(0)) - return scoreSum.dividedBy(vals.length) - }) - - return new Map(Object.entries(validatorGroupScores)) -} - -function calculateGroupWeights( - groupScores: Map, - scoreSensitivity: BigNumber -): Map { - const groupWeights = new Map() - for (const group of groupScores.keys()) { - const score = groupScores.get(group) - if (score && score.isGreaterThan(0)) { - groupWeights.set(group, score.pow(scoreSensitivity)) - } else { - groupWeights.set(group, new BigNumber(0)) - } - } - return groupWeights -} - -function getUnweightedRandomChoice(groupsToConsider: string[]): string { - const randomIndex = Math.floor(groupsToConsider.length * Math.random()) - return groupsToConsider[randomIndex] || NULL_ADDRESS -} - -function getWeightedRandomChoice( - groupWeights: Map, - groupsToConsider: string[] -): string { - // Filter to groups open to consideration, and sort from highest probability to lowest - const sortedGroupKeys = [...groupWeights.keys()] - .filter((k) => groupsToConsider.includes(k)) - .sort((a, b) => { - return groupWeights.get(b)!.comparedTo(groupWeights.get(a)!) - }) - - let weightTotal = new BigNumber(0) - for (const key of sortedGroupKeys) { - weightTotal = weightTotal.plus(groupWeights.get(key) || 0) - } - - const choice = weightTotal.multipliedBy(Math.random()) - let totalSoFar = new BigNumber(0) - - for (const key of sortedGroupKeys) { - totalSoFar = totalSoFar.plus(groupWeights.get(key)!) - if (totalSoFar.isGreaterThanOrEqualTo(choice)) { - return key - } - } - - // If this happens, it means no groups were available - return NULL_ADDRESS -} - -async function activatePendingVotes(kit: ContractKit, botKeys: string[]): Promise { - const election = await kit.contracts.getElection() - - await concurrentMap(10, botKeys, async (key) => { - kit.connection.addAccount(key) - const account = ensureLeading0x(privateKeyToAddress(key)) - if (!(await election.hasActivatablePendingVotes(account))) { - try { - const activateTxs = await election.activate(account) - await concurrentMap(10, activateTxs, (tx) => tx.sendAndWaitForReceipt({ from: account })) - } catch (error) { - console.error(`Failed to activate pending votes for ${account}`) - } - } - }) -} - -function shouldChangeVote( - score: BigNumber, - scoreSensitivity: BigNumber, - baseChangeProbability: BigNumber -): boolean { - const scoreBasedProbability = score.pow(scoreSensitivity).negated().plus(1) - const scaledProbability = scoreBasedProbability.times(baseChangeProbability.negated().plus(1)) - const totalProbability = scaledProbability.plus(baseChangeProbability) - - return totalProbability.isGreaterThan(Math.random()) -} - -function shouldBeConsidered( - groupAddress: string, - currentGroup: string | undefined, - excludedGroups: string[], - groupCapacities: Map -): boolean { - const normalizedGroupAddress = normalizeAddressWith0x(groupAddress) - const capacity = groupCapacities.get(normalizedGroupAddress) - return !!( - !excludedGroups.includes(normalizedGroupAddress) && - capacity && - capacity.isGreaterThan(0) && - (!currentGroup || !eqAddress(currentGroup, normalizedGroupAddress)) - ) -} diff --git a/packages/celotool/src/cmds/contract_addresses.ts b/packages/celotool/src/cmds/contract_addresses.ts deleted file mode 100644 index 23b07b017..000000000 --- a/packages/celotool/src/cmds/contract_addresses.ts +++ /dev/null @@ -1,42 +0,0 @@ -import * as fs from 'fs' -import { CONTRACTS_TO_COPY, downloadArtifacts, getContractAddresses } from 'src/lib/artifacts' -import { addCeloEnvMiddleware, CeloEnvArgv } from 'src/lib/env-utils' -import yargs from 'yargs' - -export const command = 'contract-addresses' - -export const describe = 'command for obtaining the contract addesses map' - -interface CopyContractArtifactsArgs extends CeloEnvArgv { - contracts: string - outputPath: string -} - -export const builder = (argv: yargs.Argv) => { - return addCeloEnvMiddleware(argv) - .option('contracts', { - default: CONTRACTS_TO_COPY.join(','), - type: 'string', - description: 'the names of the contracts separated by commas', - }) - .option('output-path', { - alias: 'o', - type: 'string', - description: 'the absolute output folder path', - }) -} - -export const handler = async (argv: CopyContractArtifactsArgs) => { - await downloadArtifacts(argv.celoEnv) - - const contractList = argv.contracts.split(',') - - const addressMap = await getContractAddresses(argv.celoEnv, contractList) - - if (argv.outputPath) { - fs.writeFileSync(argv.outputPath, JSON.stringify(addressMap, null, 2)) - } else { - // tslint:disable-next-line: no-console - console.log(addressMap) - } -} diff --git a/packages/celotool/src/cmds/copy_contract_artifacts.ts b/packages/celotool/src/cmds/copy_contract_artifacts.ts deleted file mode 100644 index ed3ceff74..000000000 --- a/packages/celotool/src/cmds/copy_contract_artifacts.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { CONTRACTS_TO_COPY, copyContractArtifacts, downloadArtifacts } from 'src/lib/artifacts' -import { addCeloEnvMiddleware, CeloEnvArgv } from 'src/lib/env-utils' -import yargs from 'yargs' - -export const command = 'copy-contract-artifacts' - -export const describe = - 'command for copying contract artifacts in a format to be easily consumed by other (typescript) packages. It will use the ABI of a particular contract and swap the address for the address of the Proxy.' - -interface CopyContractArtifactsArgs extends CeloEnvArgv { - contracts: string - outputPath: string -} - -export const builder = (argv: yargs.Argv) => { - return addCeloEnvMiddleware(argv) - .option('contracts', { - default: CONTRACTS_TO_COPY.join(','), - type: 'string', - description: 'the names of the contracts separated by commas', - }) - .option('output-path', { - required: true, - alias: 'o', - type: 'string', - description: 'the absolute output folder path', - }) -} - -export const handler = async (argv: CopyContractArtifactsArgs) => { - await downloadArtifacts(argv.celoEnv) - - const contractList = argv.contracts.split(',') - - await copyContractArtifacts(argv.celoEnv, argv.outputPath, contractList) -} diff --git a/packages/celotool/src/cmds/deploy.ts b/packages/celotool/src/cmds/deploy.ts deleted file mode 100644 index 7abad88cb..000000000 --- a/packages/celotool/src/cmds/deploy.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { addCeloEnvMiddleware, CeloEnvArgv } from 'src/lib/env-utils' -import yargs from 'yargs' - -export const command = 'deploy ' - -export const describe = 'commands for deployment of various packages in the monorepo' - -export type DeployArgv = CeloEnvArgv - -export const builder = (argv: yargs.Argv) => { - return addCeloEnvMiddleware(argv).commandDir('deploy', { extensions: ['ts'] }) -} -export const handler = () => { - // empty -} diff --git a/packages/celotool/src/cmds/deploy/clone.ts b/packages/celotool/src/cmds/deploy/clone.ts deleted file mode 100644 index 828333e63..000000000 --- a/packages/celotool/src/cmds/deploy/clone.ts +++ /dev/null @@ -1,15 +0,0 @@ -import yargs from 'yargs' -import { DeployArgv } from '../deploy' -export const command = 'clone ' - -export const describe = 'clone the initial deploy of a package in the monorepo' - -export type CloneArgv = DeployArgv - -export const builder = (argv: yargs.Argv) => { - return argv.commandDir('clone', { extensions: ['ts'] }) -} - -export const handler = () => { - // empty -} diff --git a/packages/celotool/src/cmds/deploy/destroy.ts b/packages/celotool/src/cmds/deploy/destroy.ts deleted file mode 100644 index d771e8eed..000000000 --- a/packages/celotool/src/cmds/deploy/destroy.ts +++ /dev/null @@ -1,15 +0,0 @@ -import yargs from 'yargs' -import { DeployArgv } from '../deploy' -export const command = 'destroy ' - -export const describe = 'destroy an existing deploy' - -export type DestroyArgv = DeployArgv - -export const builder = (argv: yargs.Argv) => { - return argv.commandDir('destroy', { extensions: ['ts'] }) -} - -export const handler = () => { - // empty -} diff --git a/packages/celotool/src/cmds/deploy/destroy/celostats.ts b/packages/celotool/src/cmds/deploy/destroy/celostats.ts deleted file mode 100644 index 80d1640a2..000000000 --- a/packages/celotool/src/cmds/deploy/destroy/celostats.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { removeHelmRelease } from 'src/lib/celostats' -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { exitIfCelotoolHelmDryRun } from 'src/lib/helm_deploy' -import { DestroyArgv } from '../destroy' - -export const command = 'celostats' - -export const describe = 'destroy the celostats package' - -export const builder = {} - -export const handler = async (argv: DestroyArgv) => { - exitIfCelotoolHelmDryRun() - await switchToClusterFromEnv(argv.celoEnv) - - await removeHelmRelease(argv.celoEnv) -} diff --git a/packages/celotool/src/cmds/deploy/destroy/chaoskube.ts b/packages/celotool/src/cmds/deploy/destroy/chaoskube.ts deleted file mode 100644 index 3958eae54..000000000 --- a/packages/celotool/src/cmds/deploy/destroy/chaoskube.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { helmReleaseName } from 'src/lib/chaoskube' -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { exitIfCelotoolHelmDryRun, removeGenericHelmChart } from 'src/lib/helm_deploy' -import { DestroyArgv } from '../../deploy/destroy' - -export const command = 'chaoskube' - -export const describe = 'deploy the chaoskube package' - -export const builder = {} - -export const handler = async (argv: DestroyArgv) => { - exitIfCelotoolHelmDryRun() - await switchToClusterFromEnv(argv.celoEnv) - await removeGenericHelmChart(helmReleaseName(argv.celoEnv), argv.celoEnv) -} diff --git a/packages/celotool/src/cmds/deploy/destroy/cluster.ts b/packages/celotool/src/cmds/deploy/destroy/cluster.ts deleted file mode 100644 index b4cb62058..000000000 --- a/packages/celotool/src/cmds/deploy/destroy/cluster.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { printReleases } from 'src/cmds/deploy/list' -import { deleteCluster, getNonSystemHelmReleases, switchToClusterFromEnv } from 'src/lib/cluster' -import { envTypes, envVar, fetchEnv } from 'src/lib/env-utils' -import { exitIfCelotoolHelmDryRun } from 'src/lib/helm_deploy' -import { DestroyArgv } from '../../deploy/destroy' - -export const command = 'cluster' - -export const describe = 'deletes the cluster for the given environment' - -export const builder = {} - -export const handler = async (argv: DestroyArgv) => { - exitIfCelotoolHelmDryRun() - const envType = fetchEnv(envVar.ENV_TYPE) - if (envType !== envTypes.DEVELOPMENT) { - console.error('You can only delete dev clusters') - process.exit(1) - } - - await switchToClusterFromEnv(argv.celoEnv) - const releases = await getNonSystemHelmReleases() - if (releases.length > 0) { - console.error('Cannot delete cluster, contains deployed packages that should be removed first') - printReleases(releases) - process.exit(1) - } - - await deleteCluster() -} diff --git a/packages/celotool/src/cmds/deploy/destroy/fullnodes.ts b/packages/celotool/src/cmds/deploy/destroy/fullnodes.ts deleted file mode 100644 index 107462eb9..000000000 --- a/packages/celotool/src/cmds/deploy/destroy/fullnodes.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { DestroyArgv } from 'src/cmds/deploy/destroy' -import { addContextMiddleware, ContextArgv, switchToContextCluster } from 'src/lib/context-utils' -import { removeFullNodeChart } from 'src/lib/fullnodes' -import { delinkSAForWorkloadIdentity, removeKubectlAnnotateKSA } from 'src/lib/gcloud_utils' -import { exitIfCelotoolHelmDryRun } from 'src/lib/helm_deploy' - -export const command = 'fullnodes' - -export const describe = 'deploy full-nodes in a particular context' - -type FullNodeDestroyArgv = DestroyArgv & ContextArgv - -export const builder = addContextMiddleware - -export const handler = async (argv: FullNodeDestroyArgv) => { - exitIfCelotoolHelmDryRun() - await switchToContextCluster(argv.celoEnv, argv.context) - await removeFullNodeChart(argv.celoEnv, argv.context) - await removeKubectlAnnotateKSA(argv.celoEnv, argv.context) - await delinkSAForWorkloadIdentity(argv.celoEnv, argv.context) -} diff --git a/packages/celotool/src/cmds/deploy/destroy/leaderboard.ts b/packages/celotool/src/cmds/deploy/destroy/leaderboard.ts deleted file mode 100644 index 7bb0f0506..000000000 --- a/packages/celotool/src/cmds/deploy/destroy/leaderboard.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { createClusterIfNotExists, switchToClusterFromEnv } from 'src/lib/cluster' -import { exitIfCelotoolHelmDryRun } from 'src/lib/helm_deploy' -import { removeHelmRelease } from 'src/lib/leaderboard' -import { DestroyArgv } from '../../deploy/destroy' - -export const command = 'leaderboard' - -export const describe = 'destroy the leaderboard package' - -export const builder = {} - -export const handler = async (argv: DestroyArgv) => { - exitIfCelotoolHelmDryRun() - await createClusterIfNotExists() - await switchToClusterFromEnv(argv.celoEnv) - - await removeHelmRelease(argv.celoEnv) -} diff --git a/packages/celotool/src/cmds/deploy/destroy/load-test.ts b/packages/celotool/src/cmds/deploy/destroy/load-test.ts deleted file mode 100644 index 062469d44..000000000 --- a/packages/celotool/src/cmds/deploy/destroy/load-test.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { exitIfCelotoolHelmDryRun } from 'src/lib/helm_deploy' -import { removeHelmRelease } from 'src/lib/load-test' -import { DestroyArgv } from '../../deploy/destroy' - -export const command = 'load-test' - -export const describe = 'destroy load-test deployment' - -export const builder = {} - -export const handler = async (argv: DestroyArgv) => { - exitIfCelotoolHelmDryRun() - await switchToClusterFromEnv(argv.celoEnv) - await removeHelmRelease(argv.celoEnv) -} diff --git a/packages/celotool/src/cmds/deploy/destroy/mock-oracle.ts b/packages/celotool/src/cmds/deploy/destroy/mock-oracle.ts deleted file mode 100644 index 090590fc1..000000000 --- a/packages/celotool/src/cmds/deploy/destroy/mock-oracle.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { exitIfCelotoolHelmDryRun } from 'src/lib/helm_deploy' -import { removeHelmRelease } from 'src/lib/mock-oracle' -import { DestroyArgv } from '../../deploy/destroy' - -export const command = 'mock-oracle' - -export const describe = 'destroy the mock oracle package' - -export const builder = {} - -export const handler = async (argv: DestroyArgv) => { - exitIfCelotoolHelmDryRun() - await switchToClusterFromEnv(argv.celoEnv) - - await removeHelmRelease(argv.celoEnv) -} diff --git a/packages/celotool/src/cmds/deploy/destroy/odis.ts b/packages/celotool/src/cmds/deploy/destroy/odis.ts deleted file mode 100644 index 3eebf1d17..000000000 --- a/packages/celotool/src/cmds/deploy/destroy/odis.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { addContextMiddleware, ContextArgv, switchToContextCluster } from 'src/lib/context-utils' -import { removeHelmRelease } from 'src/lib/odis' -import { DestroyArgv } from '../destroy' - -export const command = 'odis' - -export const describe = 'destroy the odis package' - -type ODISDestroyArgv = DestroyArgv & ContextArgv - -export const builder = addContextMiddleware - -export const handler = async (argv: ODISDestroyArgv) => { - await switchToContextCluster(argv.celoEnv, argv.context) - await removeHelmRelease(argv.celoEnv, argv.context) -} diff --git a/packages/celotool/src/cmds/deploy/destroy/oracle.ts b/packages/celotool/src/cmds/deploy/destroy/oracle.ts deleted file mode 100644 index 3b2bc3654..000000000 --- a/packages/celotool/src/cmds/deploy/destroy/oracle.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { flow } from 'lodash' -import { addContextMiddleware, ContextArgv, switchToContextCluster } from 'src/lib/context-utils' -import { exitIfCelotoolHelmDryRun } from 'src/lib/helm_deploy' -import { CurrencyPair } from 'src/lib/k8s-oracle/base' -import { addCurrencyPairMiddleware, getOracleDeployerForContext } from 'src/lib/oracle' -import yargs from 'yargs' -import { DestroyArgv } from '../../deploy/destroy' - -export const command = 'oracle' - -export const describe = 'destroy the oracle package' - -type OracleDestroyArgv = DestroyArgv & - ContextArgv & { - currencyPair: CurrencyPair - } - -export const builder = (argv: yargs.Argv) => { - return flow([addContextMiddleware, addCurrencyPairMiddleware])(argv) -} - -export const handler = async (argv: OracleDestroyArgv) => { - exitIfCelotoolHelmDryRun() - const clusterManager = await switchToContextCluster(argv.celoEnv, argv.context) - const deployer = getOracleDeployerForContext( - argv.celoEnv, - argv.context, - argv.currencyPair, - false, // doesn't matter if we are using forno as we are just going to remove the chart - clusterManager - ) - await deployer.removeChart() -} diff --git a/packages/celotool/src/cmds/deploy/destroy/prometheus.ts b/packages/celotool/src/cmds/deploy/destroy/prometheus.ts deleted file mode 100644 index 4af0a3d81..000000000 --- a/packages/celotool/src/cmds/deploy/destroy/prometheus.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { DestroyArgv } from 'src/cmds/deploy/destroy' -import { switchToClusterFromEnvOrContext } from 'src/lib/cluster' -import { addContextMiddleware, ContextArgv } from 'src/lib/context-utils' -import { exitIfCelotoolHelmDryRun } from 'src/lib/helm_deploy' -import { removeGrafanaHelmRelease, removePrometheus } from 'src/lib/prometheus' - -export const command = 'prometheus' - -export const describe = 'destroy prometheus chart release on a kubernetes cluster using Helm' - -export type PrometheusDestroyArgv = DestroyArgv & ContextArgv - -export const builder = (argv: PrometheusDestroyArgv) => { - return addContextMiddleware(argv) -} - -export const handler = async (argv: PrometheusDestroyArgv) => { - exitIfCelotoolHelmDryRun() - await switchToClusterFromEnvOrContext(argv, true) - - await removeGrafanaHelmRelease() - await removePrometheus() -} diff --git a/packages/celotool/src/cmds/deploy/destroy/promtail.ts b/packages/celotool/src/cmds/deploy/destroy/promtail.ts deleted file mode 100644 index 7b85886b7..000000000 --- a/packages/celotool/src/cmds/deploy/destroy/promtail.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { DestroyArgv } from 'src/cmds/deploy/destroy' -import { switchToClusterFromEnvOrContext } from 'src/lib/cluster' -import { addContextMiddleware, ContextArgv } from 'src/lib/context-utils' -import { exitIfCelotoolHelmDryRun } from 'src/lib/helm_deploy' -import { removePromtail } from 'src/lib/promtail' - -export const command = 'promtail' - -export const describe = 'destroy promtail chart release on a kubernetes cluster using Helm' - -export type PrometailDestroyArgv = DestroyArgv & ContextArgv - -export const builder = (argv: PrometailDestroyArgv) => { - return addContextMiddleware(argv) -} - -export const handler = async (argv: PrometailDestroyArgv) => { - exitIfCelotoolHelmDryRun() - - await switchToClusterFromEnvOrContext(argv, true) - - await removePromtail() -} diff --git a/packages/celotool/src/cmds/deploy/destroy/pumba.ts b/packages/celotool/src/cmds/deploy/destroy/pumba.ts deleted file mode 100644 index da90709aa..000000000 --- a/packages/celotool/src/cmds/deploy/destroy/pumba.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { exitIfCelotoolHelmDryRun, removeGenericHelmChart } from 'src/lib/helm_deploy' -import { helmReleaseName } from 'src/lib/pumba' -import { DestroyArgv } from '../../deploy/destroy' - -export const command = 'pumba' - -export const describe = 'deploy the pumba package' - -export const builder = {} - -export const handler = async (argv: DestroyArgv) => { - exitIfCelotoolHelmDryRun() - await switchToClusterFromEnv(argv.celoEnv) - await removeGenericHelmChart(helmReleaseName(argv.celoEnv), argv.celoEnv) -} diff --git a/packages/celotool/src/cmds/deploy/destroy/testnet.ts b/packages/celotool/src/cmds/deploy/destroy/testnet.ts deleted file mode 100644 index 7d531742a..000000000 --- a/packages/celotool/src/cmds/deploy/destroy/testnet.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { deleteFromCluster, deleteStaticIPs, exitIfCelotoolHelmDryRun } from 'src/lib/helm_deploy' -import { DestroyArgv } from '../../deploy/destroy' - -export const command = 'testnet' -export const describe = 'destroy an existing deploy of the testnet package' - -export const builder = {} - -export const handler = async (argv: DestroyArgv) => { - exitIfCelotoolHelmDryRun() - - await switchToClusterFromEnv(argv.celoEnv) - - await deleteFromCluster(argv.celoEnv) - await deleteStaticIPs(argv.celoEnv) -} diff --git a/packages/celotool/src/cmds/deploy/destroy/tracer-tool.ts b/packages/celotool/src/cmds/deploy/destroy/tracer-tool.ts deleted file mode 100644 index 817806589..000000000 --- a/packages/celotool/src/cmds/deploy/destroy/tracer-tool.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { exitIfCelotoolHelmDryRun } from 'src/lib/helm_deploy' -import { removeHelmRelease } from 'src/lib/tracer-tool' -import { DestroyArgv } from '../../deploy/destroy' - -export const command = 'tracer-tool' - -export const describe = 'destroy tracer-tool deployment' - -type TracerToolArgv = DestroyArgv - -export const builder = {} - -export const handler = async (argv: TracerToolArgv) => { - exitIfCelotoolHelmDryRun() - await switchToClusterFromEnv(argv.celoEnv) - await removeHelmRelease(argv.celoEnv) -} diff --git a/packages/celotool/src/cmds/deploy/destroy/transaction-metrics-exporter.ts b/packages/celotool/src/cmds/deploy/destroy/transaction-metrics-exporter.ts deleted file mode 100644 index ba936f744..000000000 --- a/packages/celotool/src/cmds/deploy/destroy/transaction-metrics-exporter.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { exitIfCelotoolHelmDryRun } from 'src/lib/helm_deploy' -import { removeHelmRelease } from 'src/lib/transaction-metrics-exporter' -import { DestroyArgv } from '../../deploy/destroy' - -export const command = 'transaction-metrics-exporter' - -export const describe = 'destroy the transaction metrics exporter deploy' - -export const builder = {} - -export const handler = async (argv: DestroyArgv) => { - exitIfCelotoolHelmDryRun() - await switchToClusterFromEnv(argv.celoEnv) - await removeHelmRelease(argv.celoEnv) -} diff --git a/packages/celotool/src/cmds/deploy/destroy/voting-bot.ts b/packages/celotool/src/cmds/deploy/destroy/voting-bot.ts deleted file mode 100644 index 8e440089f..000000000 --- a/packages/celotool/src/cmds/deploy/destroy/voting-bot.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { exitIfCelotoolHelmDryRun } from 'src/lib/helm_deploy' -import { removeHelmRelease } from 'src/lib/voting-bot' -import { DestroyArgv } from '../../deploy/destroy' - -export const command = 'voting-bot' - -export const describe = 'destroy the voting bot package' - -export const builder = {} - -export const handler = async (argv: DestroyArgv) => { - exitIfCelotoolHelmDryRun() - await switchToClusterFromEnv(argv.celoEnv) - await removeHelmRelease(argv.celoEnv) -} diff --git a/packages/celotool/src/cmds/deploy/destroy/wallet-connect.ts b/packages/celotool/src/cmds/deploy/destroy/wallet-connect.ts deleted file mode 100644 index 46046390e..000000000 --- a/packages/celotool/src/cmds/deploy/destroy/wallet-connect.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { exitIfCelotoolHelmDryRun } from 'src/lib/helm_deploy' -import { removeWalletConnect } from 'src/lib/wallet-connect' -import { DestroyArgv } from '../destroy' - -export const command = 'walletconnect' - -export const describe = 'deploy the walletconnect package' - -export const builder = {} - -export const handler = async (argv: DestroyArgv) => { - exitIfCelotoolHelmDryRun() - await switchToClusterFromEnv(argv.celoEnv) - await removeWalletConnect() -} diff --git a/packages/celotool/src/cmds/deploy/initial.ts b/packages/celotool/src/cmds/deploy/initial.ts deleted file mode 100644 index cd686443c..000000000 --- a/packages/celotool/src/cmds/deploy/initial.ts +++ /dev/null @@ -1,15 +0,0 @@ -import yargs from 'yargs' -import { DeployArgv } from '../deploy' -export const command = 'initial ' - -export const describe = 'create the initial deploy of a package in the monorepo' - -export type InitialArgv = DeployArgv - -export const builder = (argv: yargs.Argv) => { - return argv.commandDir('initial', { extensions: ['ts'] }) -} - -export const handler = () => { - // empty -} diff --git a/packages/celotool/src/cmds/deploy/initial/blockchain-api.ts b/packages/celotool/src/cmds/deploy/initial/blockchain-api.ts deleted file mode 100644 index e50a4f969..000000000 --- a/packages/celotool/src/cmds/deploy/initial/blockchain-api.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { execCmd } from 'src/lib/cmd-utils' -import { AccountType, getAddressFromEnv } from 'src/lib/generate_utils' -import { exitIfCelotoolHelmDryRun } from 'src/lib/helm_deploy' -import { UpgradeArgv } from '../../deploy/upgrade' - -export const command = 'blockchain-api' - -export const describe = 'command for upgrading blockchain-api' - -// Can't extend because yargs.Argv already has a `config` property -type BlockchainApiArgv = UpgradeArgv - -export const handler = async (argv: BlockchainApiArgv) => { - exitIfCelotoolHelmDryRun() - await switchToClusterFromEnv(argv.celoEnv) - const newFaucetAddress = getAddressFromEnv(AccountType.VALIDATOR, 0) // We use the 0th validator as the faucet - console.info(`updating blockchain-api yaml file for env ${argv.celoEnv}`) - await execCmd( - `sed -i.bak 's/FAUCET_ADDRESS: .*$/FAUCET_ADDRESS: \"${newFaucetAddress}\"/g' ../blockchain-api/app.${argv.celoEnv}.yaml` - ) - await execCmd(`rm ../blockchain-api/app.${argv.celoEnv}.yaml.bak`) // Removing temporary bak file - console.info(`deploying blockchain-api for env ${argv.config}`) - await execCmd(`yarn --cwd ../blockchain-api run deploy -n ${argv.celoEnv}`) - console.info(`blockchain-api deploy complete`) -} diff --git a/packages/celotool/src/cmds/deploy/initial/celostats.ts b/packages/celotool/src/cmds/deploy/initial/celostats.ts deleted file mode 100644 index 054a33147..000000000 --- a/packages/celotool/src/cmds/deploy/initial/celostats.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { installHelmChart } from 'src/lib/celostats' -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { InitialArgv } from '../initial' - -export const command = 'celostats' - -export const describe = 'deploy the celostats package' - -export const handler = async (argv: InitialArgv) => { - await switchToClusterFromEnv(argv.celoEnv) - await installHelmChart(argv.celoEnv) -} diff --git a/packages/celotool/src/cmds/deploy/initial/chaoskube.ts b/packages/celotool/src/cmds/deploy/initial/chaoskube.ts deleted file mode 100644 index 9068607de..000000000 --- a/packages/celotool/src/cmds/deploy/initial/chaoskube.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { helmChartDir, helmParameters, helmReleaseName } from 'src/lib/chaoskube' -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { installGenericHelmChart } from 'src/lib/helm_deploy' -import { InitialArgv } from '../../deploy/initial' - -export const command = 'chaoskube' - -export const describe = 'deploy the chaoskube package' - -export const builder = {} - -export const handler = async (argv: InitialArgv) => { - await switchToClusterFromEnv(argv.celoEnv) - await installGenericHelmChart({ - namespace: argv.celoEnv, - releaseName: helmReleaseName(argv.celoEnv), - chartDir: helmChartDir, - parameters: helmParameters(argv.celoEnv), - }) -} diff --git a/packages/celotool/src/cmds/deploy/initial/contracts.ts b/packages/celotool/src/cmds/deploy/initial/contracts.ts deleted file mode 100644 index a5544537e..000000000 --- a/packages/celotool/src/cmds/deploy/initial/contracts.ts +++ /dev/null @@ -1,102 +0,0 @@ -/* tslint:disable no-console */ -import { ContractKit, IdentityMetadataWrapper, newKitFromWeb3 } from '@celo/contractkit' -import { createNameClaim } from '@celo/contractkit/lib/identity/claims/claim' -import { concurrentMap } from '@celo/utils/lib/async' -import { LocalSigner } from '@celo/utils/lib/signatureUtils' -import { writeFileSync } from 'fs' -import { uploadArtifacts } from 'src/lib/artifacts' -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { execCmd } from 'src/lib/cmd-utils' -import { privateKeyToAddress } from 'src/lib/generate_utils' -import { exitIfCelotoolHelmDryRun } from 'src/lib/helm_deploy' -import { migrationOverrides, truffleOverrides, validatorKeys } from 'src/lib/migration-utils' -import { portForwardAnd } from 'src/lib/port_forward' -import { uploadFileToGoogleStorage } from 'src/lib/testnet-utils' -import Web3 from 'web3' -import yargs from 'yargs' -import { InitialArgv } from '../../deploy/initial' - -export const command = 'contracts' - -export const describe = 'deploy the celo smart contracts' - -type ContractsArgv = InitialArgv & { - skipFaucetting: boolean -} - -export const builder = (argv: yargs.Argv) => { - return argv.option('skipFaucetting', { - describe: 'skips allocation of cUSD to any oracle or bot accounts', - default: false, - type: 'boolean', - }) -} - -export const CLABS_VALIDATOR_METADATA_BUCKET = 'clabs_validator_metadata' - -function metadataURLForCLabsValidator(testnet: string, address: string) { - return `https://storage.googleapis.com/${CLABS_VALIDATOR_METADATA_BUCKET}/${testnet}/validator-${testnet}-${address}-metadata.json` -} - -async function makeMetadata(testnet: string, address: string, index: number, privateKey: string) { - const nameClaim = createNameClaim(`Validator ${index} on ${testnet}: ${address}`) - - const fileName = `validator-${testnet}-${address}-metadata.json` - const filePath = `/tmp/${fileName}` - - const metadata = IdentityMetadataWrapper.fromEmpty(address) - await metadata.addClaim(nameClaim, LocalSigner(privateKey)) - writeFileSync(filePath, metadata.toString()) - - await uploadFileToGoogleStorage( - filePath, - CLABS_VALIDATOR_METADATA_BUCKET, - `${testnet}/${fileName}`, - false, - 'application/json' - ) -} - -export async function registerMetadata(testnet: string, privateKey: string, index: number) { - const address = privateKeyToAddress(privateKey) - await makeMetadata(testnet, address, index, privateKey) - - const web3: Web3 = new Web3('http://localhost:8545') - const kit: ContractKit = newKitFromWeb3(web3) - kit.connection.addAccount(privateKey) - kit.connection.defaultAccount = address - - const accounts = await kit.contracts.getAccounts() - return accounts - .setMetadataURL(metadataURLForCLabsValidator(testnet, address)) - .sendAndWaitForReceipt() -} - -export const handler = async (argv: ContractsArgv) => { - exitIfCelotoolHelmDryRun() - await switchToClusterFromEnv(argv.celoEnv) - - console.log(`Deploying smart contracts to ${argv.celoEnv}`) - const cb = async () => { - await execCmd( - `yarn --cwd ../protocol run init-network -n ${argv.celoEnv} -c '${JSON.stringify( - truffleOverrides() - )}' -m '${JSON.stringify(await migrationOverrides(!argv.skipFaucetting))}'` - ) - - console.info('Register Metadata for Clabs validators') - await concurrentMap(5, validatorKeys(), (privateKey, index) => - registerMetadata(argv.celoEnv, privateKey, index) - ) - } - - try { - await portForwardAnd(argv.celoEnv, cb) - await uploadArtifacts(argv.celoEnv) - return - } catch (error) { - console.error(`Unable to deploy smart contracts to ${argv.celoEnv}`) - console.error(error) - process.exit(1) - } -} diff --git a/packages/celotool/src/cmds/deploy/initial/fullnodes.ts b/packages/celotool/src/cmds/deploy/initial/fullnodes.ts deleted file mode 100644 index 9e499c712..000000000 --- a/packages/celotool/src/cmds/deploy/initial/fullnodes.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { InitialArgv } from 'src/cmds/deploy/initial' -import { addContextMiddleware, ContextArgv, switchToContextCluster } from 'src/lib/context-utils' -import { installFullNodeChart } from 'src/lib/fullnodes' -import { kubectlAnnotateKSA, linkSAForWorkloadIdentity } from 'src/lib/gcloud_utils' -import { isCelotoolHelmDryRun } from 'src/lib/helm_deploy' -import yargs from 'yargs' - -export const command = 'fullnodes' - -export const describe = 'deploy full-nodes in a particular context' - -type FullNodeInitialArgv = InitialArgv & - ContextArgv & { - createNEG: boolean - staticNodes: boolean - } - -export const builder = (argv: yargs.Argv) => { - return addContextMiddleware(argv) - .option('createNEG', { - type: 'boolean', - description: - 'When enabled, will create a network endpoint group for the full node http & ws ports. Only works for GCP.', - default: false, - }) - .option('staticNodes', { - type: 'boolean', - description: - 'when enabled, generates node keys deterministically using the mnemonic and context, and uploads the enodes to GCS', - default: false, - }) -} - -export const handler = async (argv: FullNodeInitialArgv) => { - await switchToContextCluster(argv.celoEnv, argv.context) - if (!isCelotoolHelmDryRun()) { - await linkSAForWorkloadIdentity(argv.celoEnv, argv.context) - } else { - console.info(`Skipping Workload Identity Service account setup due to --helmdryrun.`) - } - await installFullNodeChart(argv.celoEnv, argv.context, argv.staticNodes, argv.createNEG) - if (!isCelotoolHelmDryRun()) { - await kubectlAnnotateKSA(argv.celoEnv, argv.context) - } -} diff --git a/packages/celotool/src/cmds/deploy/initial/leaderboard.ts b/packages/celotool/src/cmds/deploy/initial/leaderboard.ts deleted file mode 100644 index ae9598045..000000000 --- a/packages/celotool/src/cmds/deploy/initial/leaderboard.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { InitialArgv } from 'src/cmds/deploy/initial' -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { installHelmChart } from 'src/lib/leaderboard' -import yargs from 'yargs' - -export const command = 'leaderboard' - -export const describe = 'deploy the leaderboard for the specified network' - -export const builder = (argv: yargs.Argv) => { - return argv -} - -export const handler = async (argv: InitialArgv) => { - await switchToClusterFromEnv(argv.celoEnv) - await installHelmChart(argv.celoEnv) -} diff --git a/packages/celotool/src/cmds/deploy/initial/load-test.ts b/packages/celotool/src/cmds/deploy/initial/load-test.ts deleted file mode 100644 index 44b340ed9..000000000 --- a/packages/celotool/src/cmds/deploy/initial/load-test.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { CeloEnvArgv } from 'src/lib/env-utils' -import { installHelmChart, setArgvDefaults } from 'src/lib/load-test' -import yargs from 'yargs' - -export const command = 'load-test' - -export const describe = 'deploy load-test' - -export interface LoadTestArgv extends CeloEnvArgv { - blockscoutMeasurePercent: number - delay: number - replicas: number - threads: number -} - -export const builder = (argv: yargs.Argv) => { - return argv - .option('blockscout-measure-percent', { - type: 'number', - description: - 'Percent of transactions to measure the time it takes for blockscout to process a transaction. Should be in the range of [0, 100]', - default: 30, - }) - .option('delay', { - type: 'number', - description: - 'Number of ms a client waits between each transaction, defaults to LOAD_TEST_TX_DELAY_MS in the .env file', - default: -1, - }) - .option('replicas', { - type: 'number', - description: - 'Number of load test clients to create, defaults to LOAD_TEST_CLIENTS in the .env file', - default: -1, - }) - .option('threads', { - type: 'number', - description: - 'Number of threads for each client, defaults to LOAD_TEST_THREADS in the .env file', - default: -1, - }) -} - -export const handler = async (argv: LoadTestArgv) => { - await switchToClusterFromEnv(argv.celoEnv) - setArgvDefaults(argv) - - await installHelmChart( - argv.celoEnv, - argv.blockscoutMeasurePercent, - argv.delay, - argv.replicas, - argv.threads - ) -} diff --git a/packages/celotool/src/cmds/deploy/initial/mock-oracle.ts b/packages/celotool/src/cmds/deploy/initial/mock-oracle.ts deleted file mode 100644 index 972378b42..000000000 --- a/packages/celotool/src/cmds/deploy/initial/mock-oracle.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { InitialArgv } from 'src/cmds/deploy/initial' -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { installHelmChart } from 'src/lib/mock-oracle' -import yargs from 'yargs' - -export const command = 'mock-oracle' - -export const describe = 'deploy the mock oracle for the specified network' - -export const builder = (argv: yargs.Argv) => { - return argv -} - -export const handler = async (argv: InitialArgv) => { - await switchToClusterFromEnv(argv.celoEnv) - await installHelmChart(argv.celoEnv) -} diff --git a/packages/celotool/src/cmds/deploy/initial/notification-service.ts b/packages/celotool/src/cmds/deploy/initial/notification-service.ts deleted file mode 100644 index 2fbea7f59..000000000 --- a/packages/celotool/src/cmds/deploy/initial/notification-service.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { execCmd } from 'src/lib/cmd-utils' -import { exitIfCelotoolHelmDryRun } from 'src/lib/helm_deploy' -import { InitialArgv } from '../../deploy/initial' - -export const command = 'notification-service' -export const describe = 'command for deploying notification-service' - -export const handler = async (argv: InitialArgv) => { - exitIfCelotoolHelmDryRun() - console.info(`deploying notification-service for env ${argv.celoEnv}`) - await execCmd(`yarn --cwd ../notification-service run deploy -n ${argv.celoEnv}`) - console.info(`notification-service deploy complete`) -} diff --git a/packages/celotool/src/cmds/deploy/initial/odis.ts b/packages/celotool/src/cmds/deploy/initial/odis.ts deleted file mode 100644 index dd217a680..000000000 --- a/packages/celotool/src/cmds/deploy/initial/odis.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { InitialArgv } from 'src/cmds/deploy/initial' -import { addContextMiddleware, ContextArgv, switchToContextCluster } from 'src/lib/context-utils' -import { installODISHelmChart } from 'src/lib/odis' -import yargs from 'yargs' - -export const command = 'odis' - -export const describe = 'deploy the odis signers for the specified network' - -type OdisInitialArgv = InitialArgv & ContextArgv - -export const builder = (argv: yargs.Argv) => { - return addContextMiddleware(argv) -} - -export const handler = async (argv: OdisInitialArgv) => { - await switchToContextCluster(argv.celoEnv, argv.context) - await installODISHelmChart(argv.celoEnv, argv.context) -} diff --git a/packages/celotool/src/cmds/deploy/initial/oracle.ts b/packages/celotool/src/cmds/deploy/initial/oracle.ts deleted file mode 100644 index 51b589aa0..000000000 --- a/packages/celotool/src/cmds/deploy/initial/oracle.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { flow } from 'lodash' -import { InitialArgv } from 'src/cmds/deploy/initial' -import { addContextMiddleware, ContextArgv, switchToContextCluster } from 'src/lib/context-utils' -import { CurrencyPair } from 'src/lib/k8s-oracle/base' -import { - addCurrencyPairMiddleware, - addUseFornoMiddleware, - getOracleDeployerForContext, -} from 'src/lib/oracle' -import yargs from 'yargs' - -export const command = 'oracle' - -export const describe = 'deploy the oracle for the specified network' - -type OracleInitialArgv = InitialArgv & - ContextArgv & { - useForno: boolean - currencyPair: CurrencyPair - } - -export const builder = (argv: yargs.Argv) => { - return flow([addContextMiddleware, addCurrencyPairMiddleware, addUseFornoMiddleware])(argv) -} - -export const handler = async (argv: OracleInitialArgv) => { - const clusterManager = await switchToContextCluster(argv.celoEnv, argv.context) - const deployer = getOracleDeployerForContext( - argv.celoEnv, - argv.context, - argv.currencyPair, - argv.useForno, - clusterManager - ) - await deployer.installChart() -} diff --git a/packages/celotool/src/cmds/deploy/initial/prometheus.ts b/packages/celotool/src/cmds/deploy/initial/prometheus.ts deleted file mode 100644 index 21ea49d85..000000000 --- a/packages/celotool/src/cmds/deploy/initial/prometheus.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { InitialArgv } from 'src/cmds/deploy/initial' -import { switchToClusterFromEnvOrContext } from 'src/lib/cluster' -import { addContextMiddleware, ContextArgv } from 'src/lib/context-utils' -import { installGrafanaIfNotExists, installPrometheusIfNotExists } from 'src/lib/prometheus' - -export const command = 'prometheus' - -export const describe = 'deploy prometheus to a kubernetes cluster using Helm' - -export type PrometheusInitialArgv = InitialArgv & - ContextArgv & { - deployGrafana: boolean - skipClusterSetup: boolean - } - -export const builder = (argv: PrometheusInitialArgv) => { - return addContextMiddleware(argv) - .option('deploy-grafana', { - type: 'boolean', - description: 'Include the deployment of grafana helm chart', - default: false, - }) - .option('skipClusterSetup', { - type: 'boolean', - description: 'If you know that you can skip the cluster setup', - default: false, - }) -} - -export const handler = async (argv: PrometheusInitialArgv) => { - const clusterConfig = await switchToClusterFromEnvOrContext(argv, argv.skipClusterSetup) - - await installPrometheusIfNotExists(argv.context, clusterConfig) - if (argv.deployGrafana) { - await installGrafanaIfNotExists(argv.context, clusterConfig) - } -} diff --git a/packages/celotool/src/cmds/deploy/initial/promtail.ts b/packages/celotool/src/cmds/deploy/initial/promtail.ts deleted file mode 100644 index d60ccc4b9..000000000 --- a/packages/celotool/src/cmds/deploy/initial/promtail.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { InitialArgv } from 'src/cmds/deploy/initial' -import { switchToClusterFromEnvOrContext } from 'src/lib/cluster' -import { addContextMiddleware, ContextArgv } from 'src/lib/context-utils' -import { installPromtailIfNotExists } from 'src/lib/promtail' - -export const command = 'promtail' - -export const describe = 'deploy Promtail to a kubernetes cluster using Helm' - -export type PromtailInitialArgv = InitialArgv & ContextArgv - -export const builder = (argv: PromtailInitialArgv) => { - return addContextMiddleware(argv) -} - -export const handler = async (argv: PromtailInitialArgv) => { - // always skip cluster setup - const clusterConfig = await switchToClusterFromEnvOrContext(argv, true) - - await installPromtailIfNotExists(clusterConfig) -} diff --git a/packages/celotool/src/cmds/deploy/initial/pumba.ts b/packages/celotool/src/cmds/deploy/initial/pumba.ts deleted file mode 100644 index 3b9779d0c..000000000 --- a/packages/celotool/src/cmds/deploy/initial/pumba.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { installGenericHelmChart } from 'src/lib/helm_deploy' -import { helmChartDir, helmParameters, helmReleaseName } from 'src/lib/pumba' -import { InitialArgv } from '../../deploy/initial' - -export const command = 'pumba' - -export const describe = 'deploy the pumba package' - -export const builder = {} - -export const handler = async (argv: InitialArgv) => { - await switchToClusterFromEnv(argv.celoEnv) - await installGenericHelmChart({ - namespace: argv.celoEnv, - releaseName: helmReleaseName(argv.celoEnv), - chartDir: helmChartDir, - parameters: helmParameters(), - }) -} diff --git a/packages/celotool/src/cmds/deploy/initial/testnet.ts b/packages/celotool/src/cmds/deploy/initial/testnet.ts deleted file mode 100644 index 5374986ea..000000000 --- a/packages/celotool/src/cmds/deploy/initial/testnet.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { createClusterIfNotExists, setupCluster, switchToClusterFromEnv } from 'src/lib/cluster' -import { - createStaticIPs, - installHelmChart, - isCelotoolHelmDryRun, - pollForBootnodeLoadBalancer, -} from 'src/lib/helm_deploy' -import { uploadTestnetInfoToGoogleStorage } from 'src/lib/testnet-utils' -import yargs from 'yargs' -import { InitialArgv } from '../../deploy/initial' - -export const command = 'testnet' - -export const describe = 'deploy the testnet package' - -type TestnetInitialArgv = InitialArgv & { - skipClusterSetup: boolean - useExistingGenesis: boolean -} - -export const builder = (argv: yargs.Argv) => { - return argv - .option('skipClusterSetup', { - type: 'boolean', - description: 'If you know that you can skip the cluster setup', - default: false, - }) - .option('useExistingGenesis', { - type: 'boolean', - description: 'Instead of generating a new genesis, use an existing genesis in GCS', - default: false, - }) -} - -export const handler = async (argv: TestnetInitialArgv) => { - const createdCluster = await createClusterIfNotExists() - await switchToClusterFromEnv(argv.celoEnv) - - if (!argv.skipClusterSetup) { - await setupCluster(argv.celoEnv, createdCluster) - } - - await createStaticIPs(argv.celoEnv) - - await installHelmChart(argv.celoEnv, argv.useExistingGenesis) - if (!isCelotoolHelmDryRun()) { - // When using an external bootnode, we have to await the bootnode's LB to be up first - await pollForBootnodeLoadBalancer(argv.celoEnv) - await uploadTestnetInfoToGoogleStorage(argv.celoEnv) - } -} diff --git a/packages/celotool/src/cmds/deploy/initial/tracer-tool.ts b/packages/celotool/src/cmds/deploy/initial/tracer-tool.ts deleted file mode 100644 index 53637ca08..000000000 --- a/packages/celotool/src/cmds/deploy/initial/tracer-tool.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { execCmdWithExitOnFailure } from 'src/lib/cmd-utils' -import { isCelotoolHelmDryRun } from 'src/lib/helm_deploy' -import { installHelmChart } from 'src/lib/tracer-tool' -import yargs from 'yargs' -import { InitialArgv } from '../../deploy/initial' -export const command = 'tracer-tool' - -export const describe = 'deploy tracer-tool' - -interface TracerToolArgv extends InitialArgv { - faucet: boolean -} - -export const builder = (argv: yargs.Argv) => { - return argv.option('faucet', { - type: 'boolean', - description: 'Whether to faucet test accounts before deployment or no', - default: false, - }) -} - -const FIRST_ACCOUNT = '0x4da58d267cd465b9313fdb19b120ec591d957ad2' -const SECOND_ACCOUNT = '0xc70947239385c2422866e20b6cafffa29157e4b3' - -export const handler = async (argv: TracerToolArgv) => { - await switchToClusterFromEnv(argv.celoEnv) - - if (!argv.faucet || isCelotoolHelmDryRun()) { - console.info(`Skipping fauceting test accounts...`) - } else { - console.info(`Fauceting test accounts...`) - await execCmdWithExitOnFailure( - `yarn --cwd ${process.cwd()} run cli account faucet -e ${ - argv.celoEnv - } --account ${FIRST_ACCOUNT}` - ) - await execCmdWithExitOnFailure( - `yarn --cwd ${process.cwd()} run cli account faucet -e ${ - argv.celoEnv - } --account ${SECOND_ACCOUNT}` - ) - } - - await installHelmChart(argv.celoEnv) -} diff --git a/packages/celotool/src/cmds/deploy/initial/transaction-metrics-exporter.ts b/packages/celotool/src/cmds/deploy/initial/transaction-metrics-exporter.ts deleted file mode 100644 index d5fdc8342..000000000 --- a/packages/celotool/src/cmds/deploy/initial/transaction-metrics-exporter.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { installHelmChart } from 'src/lib/transaction-metrics-exporter' -import { InitialArgv } from '../../deploy/initial' - -export const command = 'transaction-metrics-exporter' - -export const describe = 'deploy the transaction metrics exporter' - -export const builder = {} - -export const handler = async (argv: InitialArgv) => { - await switchToClusterFromEnv(argv.celoEnv) - await installHelmChart(argv.celoEnv) -} diff --git a/packages/celotool/src/cmds/deploy/initial/voting-bot.ts b/packages/celotool/src/cmds/deploy/initial/voting-bot.ts deleted file mode 100644 index 17b6f13ce..000000000 --- a/packages/celotool/src/cmds/deploy/initial/voting-bot.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { InitialArgv } from 'src/cmds/deploy/initial' -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { isCelotoolHelmDryRun } from 'src/lib/helm_deploy' -import { ensure0x } from 'src/lib/utils' -import { installHelmChart, setupVotingBotAccounts } from 'src/lib/voting-bot' -import yargs from 'yargs' - -export const command = 'voting-bot' -export const describe = 'deploy voting-bot' - -interface VotingBotArgv extends InitialArgv { - excludedGroups?: string[] -} - -export const builder = (argv: yargs.Argv) => { - return argv.option('excludedGroups', { - type: 'string', - description: 'Addresses of Validator Group(s) that the bot should not vote for.', - coerce: (addresses) => { - return addresses.split(',').map(ensure0x) - }, - }) -} - -export const handler = async (argv: VotingBotArgv) => { - await switchToClusterFromEnv(argv.celoEnv) - if (!isCelotoolHelmDryRun()) { - await setupVotingBotAccounts(argv.celoEnv) - } - await installHelmChart(argv.celoEnv, argv.excludedGroups) -} diff --git a/packages/celotool/src/cmds/deploy/initial/wallet-connect.ts b/packages/celotool/src/cmds/deploy/initial/wallet-connect.ts deleted file mode 100644 index 993a3c45d..000000000 --- a/packages/celotool/src/cmds/deploy/initial/wallet-connect.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { installWalletConnect } from 'src/lib/wallet-connect' -import { InitialArgv } from '../../deploy/initial' - -export const command = 'walletconnect' - -export const describe = 'deploy the walletconnect package' - -export const builder = {} - -export const handler = async (argv: InitialArgv) => { - await switchToClusterFromEnv(argv.celoEnv) - await installWalletConnect() -} diff --git a/packages/celotool/src/cmds/deploy/list.ts b/packages/celotool/src/cmds/deploy/list.ts deleted file mode 100644 index f56eae663..000000000 --- a/packages/celotool/src/cmds/deploy/list.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { forEach, groupBy } from 'lodash' -import { - getNonSystemHelmReleases, - getPackageName, - HelmRelease, - switchToClusterFromEnv, -} from 'src/lib/cluster' -import { DeployArgv } from '../deploy' - -export const command = 'list' - -export const describe = 'list the deploys on the cluster given an env' - -export type ListArgv = DeployArgv - -export const builder = {} - -export const handler = async (argv: ListArgv) => { - await switchToClusterFromEnv(argv.celoEnv) - const releases = await getNonSystemHelmReleases() - printReleases(releases) -} - -export function printReleases(releases: HelmRelease[]) { - const releasesByEnv = groupBy(releases, (release) => release.Namespace) - - forEach(releasesByEnv, (envReleases, key) => { - console.info(`Environment: ${key}, Releases:\n`) - - envReleases.forEach((release) => - console.info( - ` - ${getPackageName(release.Chart)} (${release.Status}), last updated at: ${ - release.Updated - }` - ) - ) - console.info(`\n`) - }) -} diff --git a/packages/celotool/src/cmds/deploy/migrate.ts b/packages/celotool/src/cmds/deploy/migrate.ts deleted file mode 100644 index c36cef8d8..000000000 --- a/packages/celotool/src/cmds/deploy/migrate.ts +++ /dev/null @@ -1,15 +0,0 @@ -import yargs from 'yargs' -import { DeployArgv } from '../deploy' -export const command = 'migrate ' - -export const describe = 'migrate an existing deploy' - -export type MigrateArgv = DeployArgv - -export const builder = (argv: yargs.Argv) => { - return argv.commandDir('migrate', { extensions: ['ts'] }) -} - -export const handler = () => { - // empty -} diff --git a/packages/celotool/src/cmds/deploy/switch.ts b/packages/celotool/src/cmds/deploy/switch.ts deleted file mode 100644 index 8fc87e7e8..000000000 --- a/packages/celotool/src/cmds/deploy/switch.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { DeployArgv } from 'src/cmds/deploy' -import yargs from 'yargs' -export const command = 'switch ' - -export const describe = 'switch the exposed deployed service' - -export type SwitchArgv = DeployArgv - -export const builder = (argv: yargs.Argv) => { - return argv.commandDir('switch', { extensions: ['ts'] }) -} - -export const handler = () => { - // empty -} diff --git a/packages/celotool/src/cmds/deploy/upgrade.ts b/packages/celotool/src/cmds/deploy/upgrade.ts deleted file mode 100644 index 5b86da9f6..000000000 --- a/packages/celotool/src/cmds/deploy/upgrade.ts +++ /dev/null @@ -1,15 +0,0 @@ -import yargs from 'yargs' -import { DeployArgv } from '../deploy' -export const command = 'upgrade ' - -export const describe = 'upgrade an existing deploy' - -export type UpgradeArgv = DeployArgv - -export const builder = (argv: yargs.Argv) => { - return argv.commandDir('upgrade', { extensions: ['ts'] }) -} - -export const handler = () => { - // empty -} diff --git a/packages/celotool/src/cmds/deploy/upgrade/all.ts b/packages/celotool/src/cmds/deploy/upgrade/all.ts deleted file mode 100644 index 678fba6b0..000000000 --- a/packages/celotool/src/cmds/deploy/upgrade/all.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { sleep } from '@celo/utils/lib/async' -import { exitIfCelotoolHelmDryRun } from 'src/lib/helm_deploy' -import yargs from 'yargs' -import { UpgradeArgv } from '../../deploy/upgrade' -import { handler as contractsHandler } from '../initial/contracts' -import { handler as celostatsHandler } from './celostats' -import { handler as testnetHandler } from './testnet' - -export const command = 'all' - -export const describe = 'upgrades a typical deploy' - -type AllArgv = UpgradeArgv & { - reset: boolean - useExistingGenesis: boolean - skipFaucetting: boolean - tag: string - suffix: string -} - -export const builder = (argv: yargs.Argv) => { - return argv - .option('reset', { - describe: 'indicates a reset', - default: false, - type: 'boolean', - }) - .option('useExistingGenesis', { - type: 'boolean', - description: 'Instead of generating a new genesis, use an existing genesis in GCS', - default: false, - }) - .option('skipFaucetting', { - describe: 'skips allocation of cUSD to any oracle or bot accounts', - default: false, - type: 'boolean', - }) - .option('tag', { - type: 'string', - description: 'Docker image tag to deploy', - default: '', - }) - .option('suffix', { - type: 'string', - description: 'Instance suffix', - default: '', - }) -} - -export const handler = async (argv: AllArgv) => { - exitIfCelotoolHelmDryRun() - console.info('Deploy the testnet') - await testnetHandler(argv) - console.info('Deploy celostats') - await celostatsHandler(argv) - - if (argv.reset === true) { - console.info('Sleeping for 5 minutes to let pods come up') - await sleep(300000) - console.info('Deploy contracts') - await contractsHandler(argv) - } -} diff --git a/packages/celotool/src/cmds/deploy/upgrade/blockchain-api.ts b/packages/celotool/src/cmds/deploy/upgrade/blockchain-api.ts deleted file mode 100644 index 58ef25f97..000000000 --- a/packages/celotool/src/cmds/deploy/upgrade/blockchain-api.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { exitIfCelotoolHelmDryRun } from 'src/lib/helm_deploy' -import { handler as deployInitialBlockchainApiHandler } from '../../deploy/initial/blockchain-api' -import { UpgradeArgv } from '../../deploy/upgrade' - -export const command = 'blockchain-api' - -export const describe = 'command for upgrading blockchain-api' - -// Can't extend because yargs.Argv already has a `config` property -type BlockchainApiArgv = UpgradeArgv - -export const handler = async (argv: BlockchainApiArgv) => { - exitIfCelotoolHelmDryRun() - await deployInitialBlockchainApiHandler(argv) -} diff --git a/packages/celotool/src/cmds/deploy/upgrade/celostats.ts b/packages/celotool/src/cmds/deploy/upgrade/celostats.ts deleted file mode 100644 index 3c969d961..000000000 --- a/packages/celotool/src/cmds/deploy/upgrade/celostats.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { installHelmChart, removeHelmRelease, upgradeHelmChart } from 'src/lib/celostats' -import { switchToClusterFromEnv } from 'src/lib/cluster' -import yargs from 'yargs' -import { UpgradeArgv } from '../upgrade' - -export const command = 'celostats' - -export const describe = 'upgrade the celostats package' - -type CelostatsArgv = UpgradeArgv & { - reset: boolean -} - -export const builder = (argv: yargs.Argv) => { - return argv.option('reset', { - description: 'Destroy & redeploy the celostats package', - default: false, - type: 'boolean', - }) -} - -export const handler = async (argv: CelostatsArgv) => { - await switchToClusterFromEnv(argv.celoEnv) - - if (argv.reset === true) { - await removeHelmRelease(argv.celoEnv) - await installHelmChart(argv.celoEnv) - } else { - await upgradeHelmChart(argv.celoEnv) - } -} diff --git a/packages/celotool/src/cmds/deploy/upgrade/chaoskube.ts b/packages/celotool/src/cmds/deploy/upgrade/chaoskube.ts deleted file mode 100644 index 93217c28a..000000000 --- a/packages/celotool/src/cmds/deploy/upgrade/chaoskube.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { helmChartDir, helmParameters, helmReleaseName } from 'src/lib/chaoskube' -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { upgradeGenericHelmChart } from 'src/lib/helm_deploy' -import { InitialArgv } from '../../deploy/initial' - -export const command = 'chaoskube' - -export const describe = 'deploy the chaoskube package' - -export const builder = {} - -export const handler = async (argv: InitialArgv) => { - await switchToClusterFromEnv(argv.celoEnv) - await upgradeGenericHelmChart({ - namespace: argv.celoEnv, - releaseName: helmReleaseName(argv.celoEnv), - chartDir: helmChartDir, - parameters: helmParameters(argv.celoEnv), - }) -} diff --git a/packages/celotool/src/cmds/deploy/upgrade/contracts.ts b/packages/celotool/src/cmds/deploy/upgrade/contracts.ts deleted file mode 100644 index 7ed31b02c..000000000 --- a/packages/celotool/src/cmds/deploy/upgrade/contracts.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { downloadArtifacts, uploadArtifacts } from 'src/lib/artifacts' -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { execCmd } from 'src/lib/cmd-utils' -import { exitIfCelotoolHelmDryRun } from 'src/lib/helm_deploy' -import { migrationOverrides, truffleOverrides } from 'src/lib/migration-utils' -import { portForwardAnd } from 'src/lib/port_forward' -import yargs from 'yargs' -import { UpgradeArgv } from '../../deploy/upgrade' - -export const command = 'contracts' - -export const describe = 'upgrade the celo smart contracts' - -type ContractsArgv = UpgradeArgv & { - skipFaucetting: boolean -} - -export const builder = (argv: yargs.Argv) => { - return argv.option('skipFaucetting', { - describe: 'skips allocation of cUSD to any oracle or bot accounts', - default: false, - type: 'boolean', - }) -} - -export const handler = async (argv: ContractsArgv) => { - exitIfCelotoolHelmDryRun() - await switchToClusterFromEnv(argv.celoEnv) - - console.info(`Upgrading smart contracts on ${argv.celoEnv}`) - const cb = async () => { - await execCmd( - `yarn --cwd ../protocol run migrate -n ${argv.celoEnv} -c '${JSON.stringify( - truffleOverrides() - )}' -m '${JSON.stringify(await migrationOverrides(!argv.skipFaucetting))}'` - ) - } - - try { - await downloadArtifacts(argv.celoEnv) - await portForwardAnd(argv.celoEnv, cb) - await uploadArtifacts(argv.celoEnv) - process.exit(0) - } catch (error) { - console.error(`Unable to upgrade smart contracts on ${argv.celoEnv}`) - console.error(error) - process.exit(1) - } -} diff --git a/packages/celotool/src/cmds/deploy/upgrade/faucet.ts b/packages/celotool/src/cmds/deploy/upgrade/faucet.ts deleted file mode 100644 index 13a684f61..000000000 --- a/packages/celotool/src/cmds/deploy/upgrade/faucet.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { execSync } from 'child_process' -import { config } from 'dotenv' -import { downloadArtifacts, getContractAddresses } from 'src/lib/artifacts' -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { execCmd } from 'src/lib/cmd-utils' -import { addCeloEnvMiddleware, getEnvFile } from 'src/lib/env-utils' -import { - coerceMnemonicAccountType, - generatePrivateKey, - privateKeyToAddress, -} from 'src/lib/generate_utils' -import { exitIfCelotoolHelmDryRun } from 'src/lib/helm_deploy' -import { portForwardAnd } from 'src/lib/port_forward' -import yargs from 'yargs' -import { UpgradeArgv } from '../../deploy/upgrade' - -export const command = 'faucet' - -export const describe = 'upgrade the faucet (requires firebase login permissions)' - -interface UpgradeFaucetArgs extends UpgradeArgv { - firebaseProject: string -} - -export const builder = (argv: yargs.Argv) => { - return addCeloEnvMiddleware(argv).option('firebaseProject', { - type: 'string', - demand: 'Should be one of celo-faucet or celo-faucet-staging', - description: 'the name of the firebase project to use (celo-faucet or celo-faucet-staging)', - }) -} - -function getEnvMnemonic(env: string): string { - const envMemonicResult = config({ path: getEnvFile(env, '.mnemonic') }) - - if (envMemonicResult.error) { - throw envMemonicResult.error - } else if (envMemonicResult.parsed) { - return envMemonicResult.parsed.MNEMONIC as string - } - throw new Error('Could not get mnmonic') -} - -export const handler = async (argv: UpgradeFaucetArgs) => { - exitIfCelotoolHelmDryRun() - await switchToClusterFromEnv(argv.celoEnv) - console.info(`Upgrading faucet for network ${argv.celoEnv} on project ${argv.firebaseProject}`) - - try { - const mnemonic = getEnvMnemonic(argv.celoEnv) - const privateKey = generatePrivateKey(mnemonic, coerceMnemonicAccountType('faucet'), 0) - const address = privateKeyToAddress(privateKey) - - const fundFaucetAccounts = async () => { - await execCmd( - // TODO(joshua): Don't copy this from account/faucet in celotool - // TODO(yerdua): reimplement the protocol transfer script here, using - // the SDK + Web3 when the SDK can be built for multiple environments - `yarn --cwd ../protocol run transfer -n ${argv.celoEnv} -a ${address} -d 20000 -g 20000` - ) - } - - await downloadArtifacts(argv.celoEnv) - const addressMap = await getContractAddresses(argv.celoEnv, [ - 'escrow', - 'goldToken', - 'stableToken', - ]) - - console.info(`Switching to firebase project ${argv.firebaseProject}`) - await execCmd(`yarn --cwd ../faucet firebase use ${argv.firebaseProject}`) - - console.info(`Updating contract addresses for ${argv.celoEnv} on ${argv.firebaseProject}`) - await execCmd( - `yarn --cwd ../faucet cli config:set --net ${argv.celoEnv} --escrowAddress ${addressMap.escrow} --goldTokenAddress ${addressMap.goldToken} --stableTokenAddress ${addressMap.stableToken}` - ) - console.info(`Redepolying functions (neeeded for config changes to take place)`) - await execCmd('yarn --cwd ../faucet cli deploy:functions') - - // // Need to clear because we generate the same account each time here. - console.info(`Clearing accounts for network ${argv.celoEnv} on ${argv.firebaseProject}`) - await execSync(`yarn --cwd ../faucet cli accounts:clear --net ${argv.celoEnv}`, { - stdio: 'inherit', - }) - - console.info(`Adding one faucet account for network ${argv.celoEnv} on ${argv.firebaseProject}`) - await execCmd( - `yarn --cwd ../faucet cli accounts:add ${privateKey} ${address} --net ${argv.celoEnv}` - ) - - console.info(`Funding account ${address} on ${argv.celoEnv}`) - await portForwardAnd(argv.celoEnv, fundFaucetAccounts) - - console.info( - `Done updating contract addresses and funding the faucet account for network ${argv.celoEnv} in ${argv.firebaseProject}` - ) - console.info('Please double check the TX node IP address to ensure it did not change.') - process.exit(0) - } catch (error) { - console.error(`Unable to upgrade faucet on ${argv.celoEnv}`) - console.error(error) - process.exit(1) - } -} diff --git a/packages/celotool/src/cmds/deploy/upgrade/fullnodes.ts b/packages/celotool/src/cmds/deploy/upgrade/fullnodes.ts deleted file mode 100644 index 2fee4aa51..000000000 --- a/packages/celotool/src/cmds/deploy/upgrade/fullnodes.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { UpgradeArgv } from 'src/cmds/deploy/upgrade' -import { addContextMiddleware, ContextArgv, switchToContextCluster } from 'src/lib/context-utils' -import { upgradeFullNodeChart } from 'src/lib/fullnodes' -import { kubectlAnnotateKSA, linkSAForWorkloadIdentity } from 'src/lib/gcloud_utils' -import { isCelotoolHelmDryRun } from 'src/lib/helm_deploy' -import yargs from 'yargs' - -export const command = 'fullnodes' - -export const describe = 'deploy full nodes in a particular context' - -type FullNodeUpgradeArgv = UpgradeArgv & - ContextArgv & { - createNEG: boolean - reset: boolean - staticNodes: boolean - } - -export const builder = (argv: yargs.Argv) => { - return addContextMiddleware(argv) - .option('createNEG', { - type: 'boolean', - description: - 'When enabled, will create a network endpoint group for the full node http & ws ports. Only works for GCP.', - default: false, - }) - .option('reset', { - type: 'boolean', - description: 'when enabled, deletes the data volumes and redeploys the helm chart.', - default: false, - }) - .option('staticNodes', { - type: 'boolean', - description: - 'when enabled, generates node keys deterministically using the mnemonic and context, and uploads the enodes to GCS', - default: false, - }) -} - -export const handler = async (argv: FullNodeUpgradeArgv) => { - await switchToContextCluster(argv.celoEnv, argv.context) - if (!isCelotoolHelmDryRun()) { - await linkSAForWorkloadIdentity(argv.celoEnv, argv.context) - } - await upgradeFullNodeChart( - argv.celoEnv, - argv.context, - argv.reset, - argv.staticNodes, - argv.createNEG - ) - if (!isCelotoolHelmDryRun()) { - await kubectlAnnotateKSA(argv.celoEnv, argv.context) - } -} diff --git a/packages/celotool/src/cmds/deploy/upgrade/hotfix.ts b/packages/celotool/src/cmds/deploy/upgrade/hotfix.ts deleted file mode 100644 index ff5e14c55..000000000 --- a/packages/celotool/src/cmds/deploy/upgrade/hotfix.ts +++ /dev/null @@ -1,160 +0,0 @@ -// This is a more unusual Celotool command. It basically helps you to execute Hotfixes on testnets. Because constructing proposals is difficult to do via a CLI, you should define them here in code. There are two examples below that you can start from. - -import { newKitFromWeb3 } from '@celo/contractkit' -import { hotfixToHash, ProposalBuilder, proposalToJSON } from '@celo/governance' -import { privateKeyToAddress } from '@celo/utils/lib/address' -import { concurrentMap } from '@celo/utils/lib/async' -import { randomBytes } from 'crypto' -import { getFornoUrl } from 'src/lib/endpoints' -import { envVar, fetchEnv } from 'src/lib/env-utils' -import { AccountType, getPrivateKeysFor } from 'src/lib/generate_utils' -import { exitIfCelotoolHelmDryRun } from 'src/lib/helm_deploy' -import Web3 from 'web3' -import yargs from 'yargs' -import { UpgradeArgv } from '../../deploy/upgrade' - -export const command = 'hotfix' - -export const describe = 'runs a hotfix' - -type EthstatsArgv = UpgradeArgv & {} - -export const builder = (argv: yargs.Argv) => { - return argv -} - -export const handler = async (argv: EthstatsArgv) => { - exitIfCelotoolHelmDryRun() - try { - const kit = newKitFromWeb3(new Web3(getFornoUrl(argv.celoEnv))) - const governance = await kit.contracts.getGovernance() - const keys = getPrivateKeysFor( - AccountType.VALIDATOR, - fetchEnv(envVar.MNEMONIC), - parseInt(fetchEnv(envVar.VALIDATORS), 10) - ) - const addresses = keys.map(privateKeyToAddress) - - console.info('Add keys to ContractKit') - for (const key of keys) { - kit.connection.addAccount(key) - } - - // Here you'll want to assert the current state - // Example A: Update a var on a Celo Core Contract - // const attestations = await kit.contracts.getAttestations() - // const currentNumber = await attestations.attestationExpiryBlocks() - // if (currentNumber !== 727) { - // throw new Error(`Expected current number to be 727, but was ${currentNumber}`) - // } - - // Example B: Repoint a Celo Core Contract proxy - // const validatorsProxyAddress = await kit.registry.addressFor(CeloContract.Validators) - // const currentValidatorsImplementationAddress = await getImplementationOfProxy( - // kit.web3, - // validatorsProxyAddress - // ) - // const desiredImplementationAddress = '0xd18620a5eBE0235023602bB4d490E1e96703EddD' - // console.info('Current Implementation Address: ', currentValidatorsImplementationAddress) - - // console.info('\nBuild Proposal') - - const proposalBuilder = new ProposalBuilder(kit) - - // Example A - // proposalBuilder.addJsonTx({ - // contract: CeloContract.Attestations, - // function: 'setAttestationExpiryBlocks', - // // @ts-ignore - // args: [728], - // value: '0', - // }) - - // Example B - // proposalBuilder.addProxyRepointingTx(validatorsProxyAddress, desiredImplementationAddress) - - const proposal = await proposalBuilder.build() - if (proposal.length === 0) { - console.error('\nPlease see examples in hotfix.ts and add transactions') - process.exit(1) - } - // If your proposal is just made of Celo Registry contract methods, you can print it out - console.info('Proposal: ', await proposalToJSON(kit, proposal)) - - const salt = randomBytes(32) - console.info(`Salt: ${salt.toString('hex')}`) - - const proposalHash = hotfixToHash(kit, proposal, salt) - console.info(`Proposal Hash: ${proposalHash.toString('hex')}`) - - console.info('\nWhitelist the hotfix') - await concurrentMap(25, addresses, async (address, index) => { - try { - await governance.whitelistHotfix(proposalHash).sendAndWaitForReceipt({ from: address }) - } catch (error) { - console.error(`Error whitelisting for validator ${index} (${address}): ${error}`) - } - }) - - let hotfixRecord = await governance.getHotfixRecord(proposalHash) - console.info('Hotfix Record: ', hotfixRecord) - - console.info('\nApprove the hotfix') - await governance.approveHotfix(proposalHash).sendAndWaitForReceipt({ from: addresses[0] }) - hotfixRecord = await governance.getHotfixRecord(proposalHash) - console.info('Hotfix Record: ', hotfixRecord) - - // This is on master, but not on baklava yet - const canPass = await governance.isHotfixPassing(proposalHash) - const tally = await governance.hotfixWhitelistValidatorTally(proposalHash) - - if (!canPass) { - throw new Error(`Hotfix cannot pass. Currently tally is ${tally}`) - } - - console.info('\nPrepare the hotfix') - await governance.prepareHotfix(proposalHash).sendAndWaitForReceipt({ from: addresses[0] }) - hotfixRecord = await governance.getHotfixRecord(proposalHash) - console.info('\nHotfix Record: ', hotfixRecord) - - if (hotfixRecord.preparedEpoch.toNumber() === 0) { - console.error('Hotfix could not be prepared') - throw new Error() - } - console.info('\nExecute the hotfix') - await governance.executeHotfix(proposal, salt).sendAndWaitForReceipt({ from: addresses[0] }) - - hotfixRecord = await governance.getHotfixRecord(proposalHash) - console.info('\nHotfix Record: ', hotfixRecord) - - if (!hotfixRecord.executed) { - console.error('Hotfix could somehow not be executed') - throw new Error() - } - - // Assert any state to be sure it worked - - // Example A - // const newNumber = await attestations.attestationExpiryBlocks() - // if (newNumber !== 728) { - // throw new Error(`Expected current number to be 728, but was ${newNumber}`) - // } - - // Example B - // const newValidatorsImplementationAddress = await getImplementationOfProxy( - // kit.web3, - // validatorsProxyAddress - // ) - // if (!eqAddress(newValidatorsImplementationAddress, desiredImplementationAddress)) { - // throw new Error( - // `Expected new implementation address to be ${desiredImplementationAddress}, but was ${newValidatorsImplementationAddress}` - // ) - // } - - console.info('Hotfix successfully executed!') - process.exit(0) - } catch (error) { - console.error(error) - process.exit(1) - } -} diff --git a/packages/celotool/src/cmds/deploy/upgrade/leaderboard.ts b/packages/celotool/src/cmds/deploy/upgrade/leaderboard.ts deleted file mode 100644 index f8cccceb6..000000000 --- a/packages/celotool/src/cmds/deploy/upgrade/leaderboard.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { UpgradeArgv } from 'src/cmds/deploy/upgrade' -import { createClusterIfNotExists, switchToClusterFromEnv } from 'src/lib/cluster' -import { isCelotoolHelmDryRun } from 'src/lib/helm_deploy' -import { installHelmChart, removeHelmRelease, upgradeHelmChart } from 'src/lib/leaderboard' -import yargs from 'yargs' - -export const command = 'leaderboard' - -export const describe = 'upgrade the leaderboard package' - -type LeaderboardArgv = UpgradeArgv & { - reset: boolean -} - -export const builder = (argv: yargs.Argv) => { - return argv.option('reset', { - description: 'Destroy & redeploy the leaderboard package', - default: false, - type: 'boolean', - }) -} - -export const handler = async (argv: LeaderboardArgv) => { - if (!isCelotoolHelmDryRun()) { - await createClusterIfNotExists() - } - await switchToClusterFromEnv(argv.celoEnv) - - if (argv.reset === true && !isCelotoolHelmDryRun()) { - await removeHelmRelease(argv.celoEnv) - await installHelmChart(argv.celoEnv) - } else { - await upgradeHelmChart(argv.celoEnv) - } -} diff --git a/packages/celotool/src/cmds/deploy/upgrade/load-test.ts b/packages/celotool/src/cmds/deploy/upgrade/load-test.ts deleted file mode 100644 index 7ff50139d..000000000 --- a/packages/celotool/src/cmds/deploy/upgrade/load-test.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { builder as initialBuilder, LoadTestArgv } from 'src/cmds/deploy/initial/load-test' -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { isCelotoolHelmDryRun } from 'src/lib/helm_deploy' -import { resetAndUpgrade, setArgvDefaults, upgradeHelmChart } from 'src/lib/load-test' -import yargs from 'yargs' - -export const command = 'load-test' - -export const describe = 'deploy load-test' - -type LoadTestUpgradeArgv = LoadTestArgv & { - reset: boolean -} - -export const builder = (argv: yargs.Argv) => { - initialBuilder(argv).option('reset', { - description: 'Scale down all load-test clients, upgrade, and scale back up', - default: false, - type: 'boolean', - }) -} - -export const handler = async (argv: LoadTestUpgradeArgv) => { - await switchToClusterFromEnv(argv.celoEnv) - setArgvDefaults(argv) - - if (argv.reset === true && !isCelotoolHelmDryRun()) { - await resetAndUpgrade( - argv.celoEnv, - argv.blockscoutMeasurePercent, - argv.delay, - argv.replicas, - argv.threads - ) - } else { - await upgradeHelmChart( - argv.celoEnv, - argv.blockscoutMeasurePercent, - argv.delay, - argv.replicas, - argv.threads - ) - } -} diff --git a/packages/celotool/src/cmds/deploy/upgrade/odis.ts b/packages/celotool/src/cmds/deploy/upgrade/odis.ts deleted file mode 100644 index 62e3dcb39..000000000 --- a/packages/celotool/src/cmds/deploy/upgrade/odis.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { UpgradeArgv } from 'src/cmds/deploy/upgrade' -import { addContextMiddleware, ContextArgv, switchToContextCluster } from 'src/lib/context-utils' -import { upgradeODISChart } from 'src/lib/odis' -import yargs from 'yargs' - -export const command = 'odis' - -export const describe = 'upgrade odis on an AKS cluster' - -type OdisUpgradeArgv = UpgradeArgv & ContextArgv - -export const builder = (argv: yargs.Argv) => { - return addContextMiddleware(argv) -} - -export const handler = async (argv: OdisUpgradeArgv) => { - await switchToContextCluster(argv.celoEnv, argv.context) - await upgradeODISChart(argv.celoEnv, argv.context) -} diff --git a/packages/celotool/src/cmds/deploy/upgrade/oracle.ts b/packages/celotool/src/cmds/deploy/upgrade/oracle.ts deleted file mode 100644 index 43ac58cfe..000000000 --- a/packages/celotool/src/cmds/deploy/upgrade/oracle.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { flow } from 'lodash' -import { UpgradeArgv } from 'src/cmds/deploy/upgrade' -import { addContextMiddleware, ContextArgv, switchToContextCluster } from 'src/lib/context-utils' -import { CurrencyPair } from 'src/lib/k8s-oracle/base' -import { - addCurrencyPairMiddleware, - addUseFornoMiddleware, - getOracleDeployerForContext, -} from 'src/lib/oracle' -import yargs from 'yargs' - -export const command = 'oracle' - -export const describe = 'upgrade the oracle(s) on an AKS cluster' - -type OracleUpgradeArgv = UpgradeArgv & - ContextArgv & { - useForno: boolean - currencyPair: CurrencyPair - } - -export const builder = (argv: yargs.Argv) => { - return flow([addContextMiddleware, addCurrencyPairMiddleware, addUseFornoMiddleware])(argv) -} - -export const handler = async (argv: OracleUpgradeArgv) => { - const clusterManager = await switchToContextCluster(argv.celoEnv, argv.context) - const deployer = getOracleDeployerForContext( - argv.celoEnv, - argv.context, - argv.currencyPair, - argv.useForno, - clusterManager - ) - await deployer.upgradeChart() -} diff --git a/packages/celotool/src/cmds/deploy/upgrade/prometheus.ts b/packages/celotool/src/cmds/deploy/upgrade/prometheus.ts deleted file mode 100644 index 48e7a9c3a..000000000 --- a/packages/celotool/src/cmds/deploy/upgrade/prometheus.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { UpgradeArgv } from 'src/cmds/deploy/upgrade' -import { switchToClusterFromEnvOrContext } from 'src/lib/cluster' -import { addContextMiddleware, ContextArgv } from 'src/lib/context-utils' -import { upgradeGrafana, upgradePrometheus } from 'src/lib/prometheus' - -export const command = 'prometheus' - -export const describe = 'upgrade prometheus to a kubernetes cluster using Helm' - -export type PrometheusUpgradeArgv = UpgradeArgv & - ContextArgv & { - deployGrafana: boolean - } - -export const builder = (argv: PrometheusUpgradeArgv) => { - return addContextMiddleware(argv).option('deploy-grafana', { - type: 'boolean', - description: 'Include the deployment of grafana helm chart', - default: false, - }) -} - -export const handler = async (argv: PrometheusUpgradeArgv) => { - const clusterConfig = await switchToClusterFromEnvOrContext(argv, true) - - await upgradePrometheus(argv.context, clusterConfig) - - if (argv.deployGrafana) { - await upgradeGrafana(argv.context, clusterConfig) - } -} diff --git a/packages/celotool/src/cmds/deploy/upgrade/promtail.ts b/packages/celotool/src/cmds/deploy/upgrade/promtail.ts deleted file mode 100644 index df9a94d91..000000000 --- a/packages/celotool/src/cmds/deploy/upgrade/promtail.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { UpgradeArgv } from 'src/cmds/deploy/upgrade' -import { switchToClusterFromEnvOrContext } from 'src/lib/cluster' -import { addContextMiddleware, ContextArgv } from 'src/lib/context-utils' -import { upgradePromtail } from 'src/lib/promtail' - -export const command = 'promtail' - -export const describe = 'upgrade Promtail to a kubernetes cluster using Helm' - -export type PromtailUpgradeArgv = UpgradeArgv & ContextArgv - -export const builder = (argv: PromtailUpgradeArgv) => { - return addContextMiddleware(argv) -} - -export const handler = async (argv: PromtailUpgradeArgv) => { - // always skip cluster setup - const clusterConfig = await switchToClusterFromEnvOrContext(argv, true) - - await upgradePromtail(clusterConfig) -} diff --git a/packages/celotool/src/cmds/deploy/upgrade/pumba.ts b/packages/celotool/src/cmds/deploy/upgrade/pumba.ts deleted file mode 100644 index 1c2510071..000000000 --- a/packages/celotool/src/cmds/deploy/upgrade/pumba.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { upgradeGenericHelmChart } from 'src/lib/helm_deploy' -import { helmChartDir, helmParameters, helmReleaseName } from 'src/lib/pumba' -import { InitialArgv } from '../../deploy/initial' - -export const command = 'pumba' - -export const describe = 'deploy the pumba package' - -export const builder = {} - -export const handler = async (argv: InitialArgv) => { - await switchToClusterFromEnv(argv.celoEnv) - await upgradeGenericHelmChart({ - namespace: argv.celoEnv, - releaseName: helmReleaseName(argv.celoEnv), - chartDir: helmChartDir, - parameters: helmParameters(), - }) -} diff --git a/packages/celotool/src/cmds/deploy/upgrade/testnet.ts b/packages/celotool/src/cmds/deploy/upgrade/testnet.ts deleted file mode 100644 index 213d22aea..000000000 --- a/packages/celotool/src/cmds/deploy/upgrade/testnet.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { - isCelotoolHelmDryRun, - resetAndUpgradeHelmChart, - upgradeHelmChart, - upgradeStaticIPs, -} from 'src/lib/helm_deploy' -import { - uploadEnvFileToGoogleStorage, - uploadTestnetStaticNodesToGoogleStorage, -} from 'src/lib/testnet-utils' -import yargs from 'yargs' -import { UpgradeArgv } from '../../deploy/upgrade' - -export const command = 'testnet' -export const describe = 'upgrade an existing deploy of the testnet package' - -type TestnetArgv = UpgradeArgv & { - reset: boolean - useExistingGenesis: boolean -} - -export const builder = (argv: yargs.Argv) => { - return argv - .option('reset', { - describe: 'deletes any chain data in persistent volume claims', - default: false, - type: 'boolean', - }) - .option('useExistingGenesis', { - type: 'boolean', - description: 'Instead of generating a new genesis, use an existing genesis in GCS', - default: false, - }) -} - -export const handler = async (argv: TestnetArgv) => { - await switchToClusterFromEnv(argv.celoEnv) - - await upgradeStaticIPs(argv.celoEnv) - - if (argv.reset === true) { - await resetAndUpgradeHelmChart(argv.celoEnv, argv.useExistingGenesis) - } else { - await upgradeHelmChart(argv.celoEnv, argv.useExistingGenesis) - } - if (!isCelotoolHelmDryRun()) { - await uploadTestnetStaticNodesToGoogleStorage(argv.celoEnv) - await uploadEnvFileToGoogleStorage(argv.celoEnv) - } -} diff --git a/packages/celotool/src/cmds/deploy/upgrade/tracer-tool.ts b/packages/celotool/src/cmds/deploy/upgrade/tracer-tool.ts deleted file mode 100644 index ae0707ffa..000000000 --- a/packages/celotool/src/cmds/deploy/upgrade/tracer-tool.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { upgradeHelmChart } from 'src/lib/tracer-tool' -import { UpgradeArgv } from '../../deploy/upgrade' - -export const command = 'tracer-tool' - -export const describe = 'upgrade the tracer-tool deployment' - -export const builder = {} - -export const handler = async (argv: UpgradeArgv) => { - await switchToClusterFromEnv(argv.celoEnv) - await upgradeHelmChart(argv.celoEnv) -} diff --git a/packages/celotool/src/cmds/deploy/upgrade/transaction-metrics-exporter.ts b/packages/celotool/src/cmds/deploy/upgrade/transaction-metrics-exporter.ts deleted file mode 100644 index 2c9d3ed6d..000000000 --- a/packages/celotool/src/cmds/deploy/upgrade/transaction-metrics-exporter.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { upgradeHelmChart } from 'src/lib/transaction-metrics-exporter' -import { UpgradeArgv } from '../../deploy/upgrade' - -export const command = 'transaction-metrics-exporter' - -export const describe = 'upgrade the transaction metrics exporter deploy' - -export const builder = {} - -export const handler = async (argv: UpgradeArgv) => { - await switchToClusterFromEnv(argv.celoEnv) - await upgradeHelmChart(argv.celoEnv) -} diff --git a/packages/celotool/src/cmds/deploy/upgrade/wallet-connect.ts b/packages/celotool/src/cmds/deploy/upgrade/wallet-connect.ts deleted file mode 100644 index ab5ad2c02..000000000 --- a/packages/celotool/src/cmds/deploy/upgrade/wallet-connect.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { upgradeWalletConnect } from 'src/lib/wallet-connect' -import { InitialArgv } from '../initial' - -export const command = 'walletconnect' - -export const describe = 'deploy the walletconnect package' - -export const builder = {} - -export const handler = async (argv: InitialArgv) => { - await switchToClusterFromEnv(argv.celoEnv) - await upgradeWalletConnect() -} diff --git a/packages/celotool/src/cmds/fork_env.ts b/packages/celotool/src/cmds/fork_env.ts deleted file mode 100644 index e03e3185f..000000000 --- a/packages/celotool/src/cmds/fork_env.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { parse } from 'dotenv' -import { readFileSync, writeFileSync } from 'fs' -import { map, merge, reduce } from 'lodash' -import path from 'path' -import { CeloEnvArgv, genericEnvFilePath, isValidCeloEnv, monorepoRoot } from 'src/lib/env-utils' -import yargs from 'yargs' -export const command = 'fork-env ' - -export const describe = 'command for forking an environment off the default .env file' - -interface ForkEnvArgs extends CeloEnvArgv { - envVars: string - newEnvName: string -} - -export const builder = (args: yargs.Argv) => { - return args - .positional('newEnvName', { - coerce: (newEnvName: string) => { - if (isValidCeloEnv(newEnvName)) { - return newEnvName - } - - throw new Error(`Invalid new env name: ${newEnvName}`) - }, - }) - .option('envVars', { - type: 'array', - description: 'environment variables you want to override, with ENV_NAME=value', - default: [], - alias: 'e', - }) -} - -export const handler = async (argv: ForkEnvArgs) => { - const genericEnvFile = readFileSync(genericEnvFilePath) - const defaultEnvVars = parse(genericEnvFile) - - const envVarsToOverride = reduce(map(argv.envVars, parse), merge, {}) - - const mergedEnvVars = { ...defaultEnvVars, ...envVarsToOverride } - const newEnvFile = map(mergedEnvVars, (value, key) => `${key}="${value}"`).join('\n') - writeFileSync(path.resolve(monorepoRoot, `.env.${argv.newEnvName}`), newEnvFile) -} diff --git a/packages/celotool/src/cmds/gcp/remove-leaked-forwarding-rules.ts b/packages/celotool/src/cmds/gcp/remove-leaked-forwarding-rules.ts deleted file mode 100644 index 3ec996041..000000000 --- a/packages/celotool/src/cmds/gcp/remove-leaked-forwarding-rules.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { zip } from 'lodash' -import { execCmd, execCmdWithExitOnFailure } from 'src/lib/cmd-utils' -import yargs from 'yargs' - -export const command = 'remove-leaked-forwarding-rules' - -export const describe = 'Removes leaked forwarding rules that Kubernetes did not garbage collect' - -interface Argv extends yargs.Argv { - keywords: string - project: string -} - -export const builder = (argv: yargs.Argv) => { - return argv - .option('keywords', { - required: false, - default: '', - type: 'string', - description: 'comma-separated list of keywords when matched with the rule, should be deleted', - }) - .option('project', { - alias: 'p', - required: true, - type: 'string', - description: 'GCP project within which to run this command', - }) -} - -export const handler = async (argv: Argv) => { - console.info('Fetching forwarding-rules') - let rules: any[] = await execCmdWithExitOnFailure( - `gcloud compute forwarding-rules list --format=json --project=${argv.project}` - ).then(([body]) => JSON.parse(body)) - - const candidates = rules.filter((rule) => rule.target && rule.target.includes('targetPools')) - - console.info('Determining health of rules') - const shouldDelete = await Promise.all( - candidates.map(async (rule) => { - const targetComponents = rule.target.split('/') - const zone = targetComponents[8] - const target = targetComponents[10] - - try { - await execCmd( - `gcloud compute target-pools get-health ${target} --region=${zone} --format=json --project=${argv.project}`, - {}, - true - ) - return false - } catch ([error, stdout, stderr]) { - if (typeof stdout === 'string') { - const healthyInstances = JSON.parse(stdout).length - return healthyInstances === 0 - } - } - }) - ) - - const candidatesToDelete = zip(candidates, shouldDelete).filter(([, x]) => x) - console.info( - `Should delete ${candidatesToDelete.length} forwarding-rules that don't have any targets` - ) - - await Promise.all( - candidatesToDelete.map(async ([candidate]) => { - const targetComponents = candidate.target.split('/') - const zone = targetComponents[8] - const target = targetComponents[10] - - console.info(`Deleting forwarding-rule ${candidate.name}`) - await execCmdWithExitOnFailure( - `gcloud compute forwarding-rules delete ${candidate.name} ${getRegionFlag( - candidate.selfLink - )} -q --project=${argv.project}` - ) - console.info(`Deleted forwarding-rule ${candidate.name}`) - - console.info(`Deleting target-pool ${target}`) - await execCmdWithExitOnFailure( - `gcloud compute target-pools delete ${target} --region=${zone} -q --project=${argv.project}` - ) - console.info(`Deleted target-pool ${target}`) - }) - ) - - if (argv.keywords.length === 0) { - console.info(`No keywords given`) - return - } - - const keywordsToMatch = argv.keywords.split(',') - - rules = await execCmdWithExitOnFailure( - `gcloud compute forwarding-rules list --format=json --project=${argv.project}` - ).then(([body]) => JSON.parse(body)) - - const matchingRules = rules.filter((lb) => - keywordsToMatch.some( - (keyword) => lb.description.includes(keyword) || lb.target.includes(keyword) - ) - ) - - await Promise.all( - matchingRules.map(async (rule) => { - console.info(`Deleting forwarding-rule ${rule.name}`) - await execCmdWithExitOnFailure( - `gcloud compute forwarding-rules delete ${rule.name} ${getRegionFlag( - rule.selfLink - )} -q --project=${argv.project}` - ) - console.info(`Deleted forwarding-rule ${rule.name}`) - }) - ) - - return -} - -function getRegionFlag(name: string) { - const parts = name.split('/') - const regionIndicator = parts[7] - return regionIndicator === 'global' ? '--global' : `--region=${parts[8]}` -} diff --git a/packages/celotool/src/cmds/generate.ts b/packages/celotool/src/cmds/generate.ts deleted file mode 100644 index 74d75f197..000000000 --- a/packages/celotool/src/cmds/generate.ts +++ /dev/null @@ -1,10 +0,0 @@ -import yargs from 'yargs' - -export const command = 'generate ' -export const describe = 'commands for generating network parameters' - -export const builder = (argv: yargs.Argv) => argv.commandDir('generate', { extensions: ['ts'] }) - -export const handler = () => { - // empty -} diff --git a/packages/celotool/src/cmds/generate/account-address.ts b/packages/celotool/src/cmds/generate/account-address.ts deleted file mode 100644 index 40ec6ba51..000000000 --- a/packages/celotool/src/cmds/generate/account-address.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* tslint:disable no-console */ -import { - coerceMnemonicAccountType, - generateAddress, - MNEMONIC_ACCOUNT_TYPE_CHOICES, - privateKeyToAddress, -} from 'src/lib/generate_utils' -import yargs from 'yargs' - -interface AccountAddressArgv { - privateKey: string - mnemonic: string - accountType: string - index: number -} - -export const command = 'account-address' - -export const describe = 'command for generating account address from private key' - -export const builder = (argv: yargs.Argv) => { - return argv - .option('private-key', { - type: 'string', - description: 'private key', - required: false, - }) - .option('mnemonic', { - type: 'string', - description: 'BIP-39 mnemonic', - alias: 'm', - required: false, - }) - .option('accountType', { - alias: 'a', - type: 'string', - choices: MNEMONIC_ACCOUNT_TYPE_CHOICES, - required: false, - }) - .option('index', { - type: 'number', - description: 'Index of key to generate', - alias: 'i', - required: false, - }) -} - -export const handler = async (argv: AccountAddressArgv) => { - if (argv.privateKey) { - console.log(privateKeyToAddress(argv.privateKey)) - } else if (argv.mnemonic && argv.accountType && argv.index != null) { - console.log( - generateAddress(argv.mnemonic, coerceMnemonicAccountType(argv.accountType), argv.index) - ) - } else { - console.error('The --private-key or --mnemonic, --accountType and --index must be provided') - } -} diff --git a/packages/celotool/src/cmds/generate/address-from-env.ts b/packages/celotool/src/cmds/generate/address-from-env.ts deleted file mode 100644 index 7a51ce548..000000000 --- a/packages/celotool/src/cmds/generate/address-from-env.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* tslint:disable no-console */ -import { addCeloEnvMiddleware, CeloEnvArgv } from 'src/lib/env-utils' -import { - coerceMnemonicAccountType, - getAddressFromEnv, - MNEMONIC_ACCOUNT_TYPE_CHOICES, -} from 'src/lib/generate_utils' -import yargs from 'yargs' - -export const command = 'address-from-env' - -export const describe = 'command for fetching addresses as specified by the current environment' - -interface AccountAddressArgv extends CeloEnvArgv { - index: number - accountType: string -} - -export const builder = (argv: yargs.Argv) => { - return addCeloEnvMiddleware( - argv - .option('index', { - alias: 'i', - type: 'number', - description: 'account index', - demand: 'Please specifiy account index', - }) - .option('accountType', { - alias: 'a', - type: 'string', - choices: MNEMONIC_ACCOUNT_TYPE_CHOICES, - description: 'account type', - demand: 'Please specifiy account type', - required: true, - }) - ) -} - -export const handler = async (argv: CeloEnvArgv & AccountAddressArgv) => { - const validatorAddress = getAddressFromEnv( - coerceMnemonicAccountType(argv.accountType), - argv.index - ) - console.info(validatorAddress) -} diff --git a/packages/celotool/src/cmds/generate/bip32.ts b/packages/celotool/src/cmds/generate/bip32.ts deleted file mode 100644 index 87487f6c9..000000000 --- a/packages/celotool/src/cmds/generate/bip32.ts +++ /dev/null @@ -1,51 +0,0 @@ -/* tslint:disable no-console */ -import { - coerceMnemonicAccountType, - generatePrivateKey, - MNEMONIC_ACCOUNT_TYPE_CHOICES, -} from 'src/lib/generate_utils' -import yargs from 'yargs' - -interface Bip32Argv { - mnemonic: string - accountType: string - index: number -} - -export const command = 'bip32' - -export const describe = 'command for generating a private key using the bip32 standard' - -export const builder = (argv: yargs.Argv) => { - return argv - .option('mnemonic', { - type: 'string', - description: 'BIP-39 mnemonic', - demandOption: 'Please specify a mnemonic from which to derive a private key', - alias: 'm', - }) - .option('accountType', { - alias: 'a', - type: 'string', - choices: MNEMONIC_ACCOUNT_TYPE_CHOICES, - required: true, - }) - .option('index', { - type: 'number', - description: 'Index of key to generate', - demandOption: 'Please specify a key index', - alias: 'i', - }) -} - -/* - * Given a BIP-39 mnemonic, we generate a level 1 child private key using the - * BIP-32 standard. - * https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki - * https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki - */ -export const handler = async (argv: Bip32Argv) => { - console.log( - generatePrivateKey(argv.mnemonic, coerceMnemonicAccountType(argv.accountType), argv.index) - ) -} diff --git a/packages/celotool/src/cmds/generate/bootnode-enode.ts b/packages/celotool/src/cmds/generate/bootnode-enode.ts deleted file mode 100644 index d58910d53..000000000 --- a/packages/celotool/src/cmds/generate/bootnode-enode.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* tslint:disable no-console */ -import { addCeloEnvMiddleware, CeloEnvArgv } from 'src/lib/env-utils' -import { getBootnodeEnode } from 'src/lib/geth' -import yargs from 'yargs' - -export const command = 'bootnode-enode' - -export const describe = 'command for the bootnode enode address for an environment' - -export const builder = (argv: yargs.Argv) => addCeloEnvMiddleware(argv) - -export const handler = async (argv: CeloEnvArgv) => { - console.info(await getBootnodeEnode(argv.celoEnv)) -} diff --git a/packages/celotool/src/cmds/generate/faucet-load-test.ts b/packages/celotool/src/cmds/generate/faucet-load-test.ts deleted file mode 100644 index 230438f08..000000000 --- a/packages/celotool/src/cmds/generate/faucet-load-test.ts +++ /dev/null @@ -1,101 +0,0 @@ -/* tslint:disable no-console */ -import { newKit } from '@celo/contractkit' -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { convertToContractDecimals } from 'src/lib/contract-utils' -import { addCeloEnvMiddleware, CeloEnvArgv, envVar, fetchEnv } from 'src/lib/env-utils' -import { AccountType, generateAddress } from 'src/lib/generate_utils' -import { getIndexForLoadTestThread } from 'src/lib/geth' -import { portForwardAnd } from 'src/lib/port_forward' -import yargs from 'yargs' - -interface FaucetLoadTest extends CeloEnvArgv { - gold: number - dollars: number - replica_from: number - replica_to: number - threads_from: number - threads_to: number -} - -export const command = 'faucet-load-test' - -export const describe = 'command for fauceting the addresses used for load testing' - -export const builder = (argv: yargs.Argv) => { - return addCeloEnvMiddleware( - argv - .option('gold', { - type: 'number', - description: 'Celo Gold amount to transfer', - default: 10, - }) - .option('dollars', { - type: 'number', - description: 'Celo Dollars amount to transfer', - default: 10, - }) - .option('replica_from', { - type: 'number', - description: 'Index count from', - demandOption: 'Please specify a key index', - }) - .option('replica_to', { - type: 'number', - description: 'Index count to', - demandOption: 'Please specify a key index', - }) - .option('threads_from', { - type: 'number', - description: 'Index of key to generate', - demandOption: 'Please specify a key threads_from', - }) - .option('threads_to', { - type: 'number', - description: 'Index of key to generate', - demandOption: 'Please specify a key threads_to', - }) - ) -} - -export const handler = async (argv: CeloEnvArgv & FaucetLoadTest) => { - await switchToClusterFromEnv(argv.celoEnv) - const accountType = AccountType.LOAD_TESTING_ACCOUNT - const mnemonic = fetchEnv(envVar.MNEMONIC) - - const cb = async () => { - const kit = newKit('http://localhost:8545') - const account = (await kit.web3.eth.getAccounts())[0] - console.log(`Using account: ${account}`) - kit.defaultAccount = account - - const [goldToken, stableToken] = await Promise.all([ - kit.contracts.getGoldToken(), - kit.contracts.getStableToken(), - ]) - - const [goldAmount, stableTokenAmount] = await Promise.all([ - convertToContractDecimals(argv.gold, goldToken), - convertToContractDecimals(argv.dollars, stableToken), - ]) - - for (let podIndex = argv.replica_from; podIndex <= argv.replica_to; podIndex++) { - for (let threadIndex = argv.threads_from; threadIndex <= argv.threads_to; threadIndex++) { - const index = getIndexForLoadTestThread(podIndex, threadIndex) - const address = generateAddress(mnemonic, accountType, index) - console.log(`${index} --> Fauceting ${goldAmount.toFixed()} Gold to ${address}`) - await goldToken.transfer(address, goldAmount.toFixed()).send() - console.log(`${index} --> Fauceting ${stableTokenAmount.toFixed()} Dollars to ${address}`) - await stableToken.transfer(address, stableTokenAmount.toFixed()).send() - } - } - } - - try { - await portForwardAnd(argv.celoEnv, cb) - await cb - } catch (error) { - console.error(`Unable to faucet load-test accounts on ${argv.celoEnv}`) - console.error(error) - process.exit(1) - } -} diff --git a/packages/celotool/src/cmds/generate/genesis-file.ts b/packages/celotool/src/cmds/generate/genesis-file.ts deleted file mode 100644 index 28b4a63af..000000000 --- a/packages/celotool/src/cmds/generate/genesis-file.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { addCeloEnvMiddleware, CeloEnvArgv } from 'src/lib/env-utils' -import { generateGenesisFromEnv } from 'src/lib/generate_utils' -import yargs from 'yargs' - -export const command = 'genesis-file' - -export const describe = 'command for creating the genesis file by the current environment' - -type GenesisFileArgv = CeloEnvArgv - -export const builder = (argv: yargs.Argv) => { - return addCeloEnvMiddleware(argv) -} - -export const handler = async (_argv: GenesisFileArgv) => { - const genesisFile = generateGenesisFromEnv() - console.info(genesisFile) -} diff --git a/packages/celotool/src/cmds/generate/istanbul-extra.ts b/packages/celotool/src/cmds/generate/istanbul-extra.ts deleted file mode 100644 index 73810ccf5..000000000 --- a/packages/celotool/src/cmds/generate/istanbul-extra.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { readFileSync } from 'fs' -import { addCeloEnvMiddleware, CeloEnvArgv, envVar, fetchEnv } from 'src/lib/env-utils' -import { - generateIstanbulExtraData, - getValidatorsInformation, - Validator, -} from 'src/lib/generate_utils' -import yargs from 'yargs' - -export const command = 'istanbul-extra' - -export const describe = - 'command to compile the istanbul extra data to include in a custom genesis file' - -interface IstanbulExtraArgv extends CeloEnvArgv { - validators: string -} - -export const builder = (argv: yargs.Argv) => { - return addCeloEnvMiddleware( - argv.option('validators', { - type: 'string', - description: 'path to a validators JSON file or the keywod "env"', - demand: 'Please specify the valdiators to include', - required: true, - }) - ) -} - -export const handler = async (argv: IstanbulExtraArgv) => { - const validators: Validator[] = - argv.validators === 'env' - ? getValidatorsInformation( - fetchEnv(envVar.MNEMONIC), - parseInt(fetchEnv(envVar.VALIDATORS), 10) - ) - : JSON.parse(readFileSync(argv.validators).toString()) - console.info(validators) - console.info('\nIstanbul extra data:') - const extra = generateIstanbulExtraData(validators) - console.info(extra) -} diff --git a/packages/celotool/src/cmds/generate/prepare-load-test-client.ts b/packages/celotool/src/cmds/generate/prepare-load-test-client.ts deleted file mode 100644 index 07da73f9a..000000000 --- a/packages/celotool/src/cmds/generate/prepare-load-test-client.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* tslint:disable no-console */ -import * as fs from 'fs' -import { AccountType, generatePrivateKey, privateKeyToAddress } from 'src/lib/generate_utils' -import yargs from 'yargs' - -interface Bip32Argv { - mnemonic: string - index: number - threads: number -} - -export const command = 'prepare-load-test' - -export const describe = - 'command for generating public and private keys for a load test instance. Expected to run inside the loadtest pod' - -export const builder = (argv: yargs.Argv) => { - return argv - .option('mnemonic', { - type: 'string', - description: 'BIP-39 mnemonic', - demandOption: 'Please specify a mnemonic from which to derive a private key', - alias: 'm', - }) - .option('index', { - type: 'number', - description: 'Index of key to generate', - demandOption: 'Please specify a key index', - alias: 'i', - }) - .option('threads', { - type: 'number', - description: 'The number of threads', - demandOption: 'Please specify the number of threads of this node', - alias: 't', - }) -} - -export const handler = async (argv: Bip32Argv) => { - const accountType = AccountType.LOAD_TESTING_ACCOUNT - for (let t = 0; t < argv.threads; t++) { - const index = argv.index * 10000 + t - - const privateKey = generatePrivateKey(argv.mnemonic, accountType, index) - const address = privateKeyToAddress(privateKey) - fs.writeFileSync(`/root/.celo/pkey${t}`, `${privateKey}\n`) - fs.appendFileSync(`/root/.celo/address`, `${address}\n`) - console.log(`Address for index ${argv.index} and thread ${t} --> ${address}`) - } -} diff --git a/packages/celotool/src/cmds/generate/public-key.ts b/packages/celotool/src/cmds/generate/public-key.ts deleted file mode 100644 index 43b33f6e9..000000000 --- a/packages/celotool/src/cmds/generate/public-key.ts +++ /dev/null @@ -1,54 +0,0 @@ -/* tslint:disable no-console */ -import { - coerceMnemonicAccountType, - generatePrivateKey, - MNEMONIC_ACCOUNT_TYPE_CHOICES, - privateKeyToPublicKey, -} from 'src/lib/generate_utils' -import yargs from 'yargs' - -interface Bip32Argv { - mnemonic: string - accountType: string - index: number -} - -export const command = 'public-key' - -export const describe = 'command for generating the public key using the bip32 standard' - -export const builder = (argv: yargs.Argv) => { - return argv - .option('mnemonic', { - type: 'string', - description: 'BIP-39 mnemonic', - demandOption: 'Please specify a mnemonic from which to derive a public key', - alias: 'm', - }) - .option('accountType', { - alias: 'a', - type: 'string', - choices: MNEMONIC_ACCOUNT_TYPE_CHOICES, - required: true, - }) - .option('index', { - type: 'number', - description: 'Index of key to generate', - demandOption: 'Please specify a key index', - alias: 'i', - }) -} - -/* - * Given a BIP-39 mnemonic, we generate a level 2 child public key from the private key using the - * BIP-32 standard. - * https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki - * https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki - */ -export const handler = async (argv: Bip32Argv) => { - console.log( - privateKeyToPublicKey( - generatePrivateKey(argv.mnemonic, coerceMnemonicAccountType(argv.accountType), argv.index) - ) - ) -} diff --git a/packages/celotool/src/cmds/geth.ts b/packages/celotool/src/cmds/geth.ts deleted file mode 100644 index 4198222c9..000000000 --- a/packages/celotool/src/cmds/geth.ts +++ /dev/null @@ -1,18 +0,0 @@ -import yargs from 'yargs' - -export const command = 'geth ' - -export const describe = 'commands for geth' - -export interface GethArgv extends yargs.Argv { - gethDir: string - dataDir: string -} - -export const builder = (argv: yargs.Argv) => { - return argv.commandDir('geth', { extensions: ['ts'] }) -} - -export const handler = () => { - // empty -} diff --git a/packages/celotool/src/cmds/geth/build.ts b/packages/celotool/src/cmds/geth/build.ts deleted file mode 100644 index aac4b0b68..000000000 --- a/packages/celotool/src/cmds/geth/build.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { execCmdWithExitOnFailure } from 'src/lib/cmd-utils' -import yargs from 'yargs' -import { GethArgv } from '../geth' - -export const command = 'build' - -export const describe = 'command for building geth' - -interface BuildArgv extends GethArgv { - clean: boolean -} - -export const builder = (argv: yargs.Argv) => { - return argv - .option('geth-dir', { - type: 'string', - description: 'path to geth repository', - demand: 'Please, specify the path to geth directory, where the binary could be found', - }) - .option('clean', { - type: 'boolean', - alias: 'c', - description: 'whether to clean before make', - default: false, - }) -} - -export const handler = async (argv: BuildArgv) => { - const cmd = argv.clean ? `make clean && make -j` : `make -j` - await execCmdWithExitOnFailure(cmd, { cwd: argv.gethDir }) - - console.info(`Geth has been built successfully!`) -} diff --git a/packages/celotool/src/cmds/geth/create_account.ts b/packages/celotool/src/cmds/geth/create_account.ts deleted file mode 100644 index 5104f5e8b..000000000 --- a/packages/celotool/src/cmds/geth/create_account.ts +++ /dev/null @@ -1,94 +0,0 @@ -/* tslint:disable no-console */ -import fs from 'fs' -import path from 'path' -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { execCmd, execCmdWithExitOnFailure } from 'src/lib/cmd-utils' -import { addCeloEnvMiddleware, CeloEnvArgv } from 'src/lib/env-utils' -import { fetchPassword } from 'src/lib/geth' -import { addCeloGethMiddleware } from 'src/lib/utils' -import yargs from 'yargs' -import { GethArgv } from '../geth' - -export const command = 'create-account' - -export const describe = 'command for creating account and fauceting it' - -interface CreateAccountArgv extends CeloEnvArgv, GethArgv { - faucet: boolean - password: string - passwordFile: string | null -} - -export const builder = (argv: yargs.Argv) => { - return addCeloGethMiddleware(addCeloEnvMiddleware(argv)) - .option('faucet', { - type: 'boolean', - alias: 'f', - default: false, - description: - 'whether to faucet created account with 100 celo dollars and 10 celo gold or not', - }) - .option('password', { - type: 'string', - description: 'account password', - default: '', - }) - .option('password-file', { - type: 'string', - description: 'path to file with account password', - default: null, - }) -} - -export const handler = async (argv: CreateAccountArgv) => { - await switchToClusterFromEnv(argv.celoEnv, false) - - const env = argv.celoEnv - let password = argv.password - const datadir = argv.dataDir - const passwordFile = argv.passwordFile - const needFaucet = argv.faucet - const gethBinary = `${argv.gethDir}/build/bin/geth` - - if (!fs.existsSync(path.resolve(datadir, 'keystore'))) { - console.error(`Error: keystore was not found in datadir ${datadir}`) - console.info(`Try to running "celotooljs geth init"`) - process.exit(1) - } - - if (password.length > 0 && passwordFile !== null) { - console.error(`Please, specify either "password" or "password-file" but not both`) - process.exit(1) - } - - if (passwordFile !== null) { - password = fetchPassword(passwordFile) - } - - const passwordFilePath = path.resolve(__dirname, '__password_tmp') - fs.writeFileSync(passwordFilePath, password) - - const [stdout, stderr] = await execCmd( - `${gethBinary} --datadir=${datadir} account new --password ${passwordFilePath}` - ) - - fs.unlinkSync(passwordFilePath) - - const addressRegex = /Address:.*{([a-zA-Z0-9]+)}/ - const matches = addressRegex.exec(stdout) - if (matches && matches.length === 2) { - const address = matches[1] - console.info(`Created account address: 0x${address}`) - - if (needFaucet) { - console.log(`Fauceting 0x${address} on ${env}`) - await execCmdWithExitOnFailure( - `yarn --cwd ${process.cwd()} run cli account faucet -e ${env} --account 0x${address}` - ) - console.info(`Fauceting completed successfully! 💰💰💰`) - } - } else { - console.error('Error occured while creating account') - console.error(`stderr: ${stderr}`) - } -} diff --git a/packages/celotool/src/cmds/geth/genesis_default.json b/packages/celotool/src/cmds/geth/genesis_default.json deleted file mode 100644 index bdbcb5cc9..000000000 --- a/packages/celotool/src/cmds/geth/genesis_default.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "config": { - "chainId": 1101, - "homesteadBlock": 1, - "eip150Block": 2, - "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "eip155Block": 3, - "eip158Block": 3, - "byzantiumBlock": 4, - "clique": { - "period": 5, - "epoch": 30000 - } - }, - "nonce": "0x0", - "timestamp": "0x5b843511", - "extraData": - "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000feE1a22F43BeeCB912B5a4912ba87527682ef0fC889F21CE69dcc25a4594f73230A55896d67038065372d2bbBaBaAf1495182E31cF13dB0d18463B0EF71690ea7E0c67827d8968882FAC0c4cBBD65BCE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "gasLimit": "0x8000000", - "difficulty": "0x0400", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "coinbase": "0x0000000000000000000000000000000000000000", - "alloc": { - "feE1a22F43BeeCB912B5a4912ba87527682ef0fC": { - "balance": "1000000000000000000000000" - }, - "889F21CE69dcc25a4594f73230A55896d6703806": { - "balance": "1000000000000000000000000" - }, - "5372d2bbBaBaAf1495182E31cF13dB0d18463B0E": { - "balance": "1000000000000000000000000" - }, - "F71690ea7E0c67827d8968882FAC0c4cBBD65BCE": { - "balance": "1000000000000000000000000" - }, - "0000000000000000000000000000000000000abe": { - "code": - "0x60806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806303386ba3146100df57806342404e071461012d578063bb913f4114610184578063d29d44ee146101c7578063f7e6af801461020a575b600060405180807f6f72672e63656c6f2e696d706c656d656e746174696f6e000000000000000000815250601701905060405180910390209050805460405136810160405236600082376000803683855af43d604051818101604052816000823e82600081146100db578282f35b8282fd5b61012b600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001908201803590602001919091929391929390505050610261565b005b34801561013957600080fd5b5061014261031d565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561019057600080fd5b506101c5600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610360565b005b3480156101d357600080fd5b50610208600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061044b565b005b34801561021657600080fd5b5061021f6104bf565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b600061026b6104bf565b905060008173ffffffffffffffffffffffffffffffffffffffff1614806102bd57508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b15156102c857600080fd5b6102d184610360565b8373ffffffffffffffffffffffffffffffffffffffff16838360405180838380828437820191505092505050600060405180830381855af4915050151561031757600080fd5b50505050565b60008060405180807f6f72672e63656c6f2e696d706c656d656e746174696f6e000000000000000000815250601701905060405180910390209050805491505090565b60008061036b6104bf565b905060008173ffffffffffffffffffffffffffffffffffffffff1614806103bd57508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b15156103c857600080fd5b60405180807f6f72672e63656c6f2e696d706c656d656e746174696f6e0000000000000000008152506017019050604051809103902091508282558273ffffffffffffffffffffffffffffffffffffffff167fab64f92ab780ecbf4f3866f57cee465ff36c89450dcce20237ca7a8d81fb7d1360405160405180910390a2505050565b60006104556104bf565b905060008173ffffffffffffffffffffffffffffffffffffffff1614806104a757508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b15156104b257600080fd5b6104bb82610502565b5050565b60008060405180807f6f72672e63656c6f2e6f776e6572000000000000000000000000000000000000815250600e01905060405180910390209050805491505090565b600060405180807f6f72672e63656c6f2e6f776e6572000000000000000000000000000000000000815250600e019050604051809103902090508181558173ffffffffffffffffffffffffffffffffffffffff167f50146d0e3c60aa1d17a70635b05494f864e86144a2201275021014fbf08bafe260405160405180910390a250505600a165627a7a723058202e143bd88c74e9d3753b7bec1719bf5907ae012bc140b9b2b6edf2f9b686ff5d0029", - "storage": { - "0x34dc5a2556b2030988481969696f29fed38d45813d8003f6c70e5c16ac92ae0f": - "feE1a22F43BeeCB912B5a4912ba87527682ef0fC" - }, - "balance": "0" - }, - "000000000000000000000000000000000000ce10": { - "code": - "0x60806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806303386ba3146100df57806342404e071461012d578063bb913f4114610184578063d29d44ee146101c7578063f7e6af801461020a575b600060405180807f6f72672e63656c6f2e696d706c656d656e746174696f6e000000000000000000815250601701905060405180910390209050805460405136810160405236600082376000803683855af43d604051818101604052816000823e82600081146100db578282f35b8282fd5b61012b600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001908201803590602001919091929391929390505050610261565b005b34801561013957600080fd5b5061014261031d565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561019057600080fd5b506101c5600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610360565b005b3480156101d357600080fd5b50610208600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061044b565b005b34801561021657600080fd5b5061021f6104bf565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b600061026b6104bf565b905060008173ffffffffffffffffffffffffffffffffffffffff1614806102bd57508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b15156102c857600080fd5b6102d184610360565b8373ffffffffffffffffffffffffffffffffffffffff16838360405180838380828437820191505092505050600060405180830381855af4915050151561031757600080fd5b50505050565b60008060405180807f6f72672e63656c6f2e696d706c656d656e746174696f6e000000000000000000815250601701905060405180910390209050805491505090565b60008061036b6104bf565b905060008173ffffffffffffffffffffffffffffffffffffffff1614806103bd57508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b15156103c857600080fd5b60405180807f6f72672e63656c6f2e696d706c656d656e746174696f6e0000000000000000008152506017019050604051809103902091508282558273ffffffffffffffffffffffffffffffffffffffff167fab64f92ab780ecbf4f3866f57cee465ff36c89450dcce20237ca7a8d81fb7d1360405160405180910390a2505050565b60006104556104bf565b905060008173ffffffffffffffffffffffffffffffffffffffff1614806104a757508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b15156104b257600080fd5b6104bb82610502565b5050565b60008060405180807f6f72672e63656c6f2e6f776e6572000000000000000000000000000000000000815250600e01905060405180910390209050805491505090565b600060405180807f6f72672e63656c6f2e6f776e6572000000000000000000000000000000000000815250600e019050604051809103902090508181558173ffffffffffffffffffffffffffffffffffffffff167f50146d0e3c60aa1d17a70635b05494f864e86144a2201275021014fbf08bafe260405160405180910390a250505600a165627a7a723058202e143bd88c74e9d3753b7bec1719bf5907ae012bc140b9b2b6edf2f9b686ff5d0029", - "storage": { - "0x34dc5a2556b2030988481969696f29fed38d45813d8003f6c70e5c16ac92ae0f": - "feE1a22F43BeeCB912B5a4912ba87527682ef0fC" - }, - "balance": "0" - } - }, - "number": "0x0", - "gasUsed": "0x0", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000" -} diff --git a/packages/celotool/src/cmds/geth/get_gold_balance.ts b/packages/celotool/src/cmds/geth/get_gold_balance.ts deleted file mode 100644 index 35e9613b1..000000000 --- a/packages/celotool/src/cmds/geth/get_gold_balance.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { execCmdWithExitOnFailure } from 'src/lib/cmd-utils' -import { addCeloEnvMiddleware } from 'src/lib/env-utils' -import { addCeloGethMiddleware, ensure0x } from 'src/lib/utils' -import yargs from 'yargs' -import { GethArgv } from '../geth' - -export const command = 'get gold balance' - -export const describe = 'command for initializing geth' - -interface GetGoldBalanceArgv extends GethArgv { - account: string -} - -export const builder = (argv: yargs.Argv) => { - return addCeloGethMiddleware(addCeloEnvMiddleware(argv)).option('account', { - type: 'string', - description: 'Account to get balance for', - default: null, - }) -} - -const invalidArgumentExit = (argumentName?: string, errorMessage?: string) => { - console.error(`Invalid argument ${argumentName}: ${errorMessage}`) - process.exit(1) -} - -export const handler = async (argv: GetGoldBalanceArgv) => { - const gethBinary = `${argv.gethDir}/build/bin/geth` - const datadir = argv.dataDir - let account = argv.account - - if (account === null || account.length === 0) { - invalidArgumentExit(account, 'Account must be provided') - // This return is required to prevent false lint errors in the code following this line - return - } - account = ensure0x(account) - if (account.length !== 42) { - invalidArgumentExit(account, 'Account must be 40 hex-chars') - } - - const jsCmd = `eth.getBalance\('${account}'\)` - const returnValues = await execGethJsCmd(gethBinary, datadir, jsCmd) - console.info('Gold balance: ' + returnValues[0]) -} - -export const execGethJsCmd = (gethBinary: string, datadir: string, jsCmd: string) => { - return execCmdWithExitOnFailure(`${gethBinary} -datadir "${datadir}" attach --exec "${jsCmd}"`) -} diff --git a/packages/celotool/src/cmds/geth/init.ts b/packages/celotool/src/cmds/geth/init.ts deleted file mode 100644 index dcebac73d..000000000 --- a/packages/celotool/src/cmds/geth/init.ts +++ /dev/null @@ -1,78 +0,0 @@ -import fs from 'fs' -import path from 'path' -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { execCmdWithExitOnFailure } from 'src/lib/cmd-utils' -import { addCeloEnvMiddleware, CeloEnvArgv } from 'src/lib/env-utils' -import { getEnodesAddresses, writeStaticNodes } from 'src/lib/geth' -import { addCeloGethMiddleware } from 'src/lib/utils' -import yargs from 'yargs' -import { GethArgv } from '../geth' - -const STATIC_NODES_FILE_NAME = 'static-nodes.json' -const DEFAULT_GENESIS_FILE_NAME = 'genesis_default.json' - -export const command = 'init' - -export const describe = 'command for initializing geth' - -interface InitArgv extends CeloEnvArgv, GethArgv { - genesis: string | null - fetchStaticNodesFromNetwork: boolean | null -} - -export const builder = (argv: yargs.Argv) => { - return addCeloGethMiddleware(addCeloEnvMiddleware(argv)) - .option('genesis', { - type: 'string', - description: - 'path to genesis.json | default genesis_default.json will be used if not specified', - default: null, - }) - .option('fetch-static-nodes-from-network', { - type: 'boolean', - description: 'Automically fetch static nodes from the network', - default: true, - }) -} - -const invalidArgumentExit = (argumentName: string, errorMessage: string) => { - console.error(`Invalid argument ${argumentName}: ${errorMessage}`) - process.exit(1) -} - -export const handler = async (argv: InitArgv) => { - const namespace = argv.celoEnv - const gethBinary = `${argv.gethDir}/build/bin/geth` - const datadir = argv.dataDir - const genesis = argv.genesis ? argv.genesis : path.resolve(__dirname, DEFAULT_GENESIS_FILE_NAME) - - if ( - fs.existsSync(path.resolve(datadir, STATIC_NODES_FILE_NAME)) || - fs.existsSync(path.resolve(datadir, 'geth')) - ) { - invalidArgumentExit('datadir', `Looks like geth has been already initialized in dir ${datadir}`) - } - - if (!fs.existsSync(datadir)) { - // Directory does not exist, create it. - fs.mkdirSync(datadir) - } - - if (!fs.lstatSync(datadir).isDirectory()) { - invalidArgumentExit('datadir', `${datadir} is not a directory`) - } - - if (!fs.existsSync(genesis)) { - invalidArgumentExit('genesis', `No such file: ${genesis}`) - } - - await execCmdWithExitOnFailure(`${gethBinary} --datadir "${datadir}" init ${genesis}`) - - if (argv.fetchStaticNodesFromNetwork) { - await switchToClusterFromEnv(argv.celoEnv, false) - await getEnodesAddresses(namespace).then((enodes) => { - writeStaticNodes(enodes, datadir, STATIC_NODES_FILE_NAME) - console.info(`Geth has been initialized successfully! 😎`) - }) - } -} diff --git a/packages/celotool/src/cmds/geth/run.ts b/packages/celotool/src/cmds/geth/run.ts deleted file mode 100644 index 97b051074..000000000 --- a/packages/celotool/src/cmds/geth/run.ts +++ /dev/null @@ -1,155 +0,0 @@ -import { spawnSync } from 'child_process' -import fs from 'fs' -import path from 'path' -import { addCeloGethMiddleware, ensure0x, validateAccountAddress } from 'src/lib/utils' -import yargs from 'yargs' -import { GethArgv } from '../geth' - -const STATIC_NODES_FILE_NAME = 'static-nodes.json' - -export const command = 'run' - -export const describe = 'command for running geth' - -interface RunArgv extends GethArgv { - networkId: string - syncMode: string - mining: boolean - minerAddress: string - nodekeyhex: string - minerGasPrice: number - port: number - rpcport: number - wsport: number - verbosity: number -} - -export const builder = (argv: yargs.Argv) => { - return addCeloGethMiddleware(argv) - .option('network-id', { - type: 'string', - description: 'network id', - default: '1101', - }) - .option('sync-mode', { - choices: ['full', 'fast', 'light', 'lightest'], - demandOption: true, - }) - .option('mining', { - type: 'boolean', - description: 'Is mining enabled', - default: false, - }) - .option('miner-address', { - type: 'string', - description: 'Address of the miner', - default: null, - }) - .option('nodekeyhex', { - type: 'string', - description: 'P2P node key as hex', - default: null, - }) - .option('miner-gas-price', { - type: 'number', - description: 'Mining gas price', - default: 0, - }) - .option('port', { - type: 'number', - description: 'Port', - default: 30303, - }) - .option('rpcport', { - type: 'number', - description: 'HTTP-RPC server listening port', - default: 8545, - }) - .option('wsport', { - type: 'number', - description: 'WS-RPC server listening port', - default: 8546, - }) - .option('verbosity', { - type: 'number', - description: 'Verbosity level', - default: 5, - }) - .coerce('miner-address', (minerAddress: string) => - minerAddress === null ? null : ensure0x(minerAddress) - ) -} - -export const handler = async (argv: RunArgv) => { - const gethBinary = `${argv.gethDir}/build/bin/geth` - const datadir = argv.dataDir - const networkId = argv.networkId - const syncMode = argv.syncMode - const verbosity = argv.verbosity - const nodekeyhex = argv.nodekeyhex - const port = argv.port - const rpcport = argv.rpcport - const wsport = argv.wsport - - console.info(`sync mode is ${syncMode}`) - const mining = argv.mining - const minerAddress = argv.minerAddress - const minerGasPrice = argv.minerGasPrice - - if (!fs.existsSync(path.resolve(datadir, STATIC_NODES_FILE_NAME))) { - console.error(`Error: static-nodes.json was not found in datadir ${datadir}`) - console.info(`Try running "celotooljs geth static-nodes" or "celotooljs geth init"`) - process.exit(1) - } - - const gethArgs = [ - '--datadir', - datadir, - '--syncmode', - syncMode, - '--rpc', - '--ws', - `--wsport=${wsport}`, - '--wsorigins=*', - '--rpcapi=eth,net,web3,debug,admin,personal', - '--debug', - `--port=${port}`, - '--nodiscover', - `--rpcport=${rpcport}`, - '--rpcvhosts=*', - '--networkid', - networkId, - '--verbosity', - verbosity.toString(), - '--consoleoutput=stdout', // Send all logs to stdout - '--consoleformat=term', - '--istanbul.lookbackwindow=2', - ] - - if (nodekeyhex !== null && nodekeyhex.length > 0) { - gethArgs.push('--nodekeyhex', nodekeyhex) - } - - if (mining) { - if (syncMode !== 'full' && syncMode !== 'fast') { - console.error('Mining works only in full or fast mode') - process.exit(1) - } - - if (!validateAccountAddress(minerAddress)) { - console.error(`Miner address is incorrect: "${minerAddress}"`) - process.exit(1) - } - - gethArgs.push( - '--mine', - `--miner.gasprice=${minerGasPrice}`, - '--password=/dev/null', - `--unlock=${minerAddress}`, - '--light.serve=90', - '--allow-insecure-unlock' // geth1.9 to use http w/unlocking - ) - } - - spawnSync(gethBinary, gethArgs, { stdio: 'inherit' }) -} diff --git a/packages/celotool/src/cmds/geth/simulate_client.ts b/packages/celotool/src/cmds/geth/simulate_client.ts deleted file mode 100644 index d5f9a42c9..000000000 --- a/packages/celotool/src/cmds/geth/simulate_client.ts +++ /dev/null @@ -1,153 +0,0 @@ -/* tslint:disable no-console */ -import BigNumber from 'bignumber.js' -import { AccountType, generateAddress, generatePrivateKey } from 'src/lib/generate_utils' -import { - getIndexForLoadTestThread, - MAX_LOADTEST_THREAD_COUNT, - simulateClient, - TestMode, -} from 'src/lib/geth' -import * as yargs from 'yargs' -export const command = 'simulate-client' - -export const describe = 'command for simulating client behavior' - -interface SimulateClientArgv extends yargs.Argv { - blockscoutMeasurePercent: number - blockscoutUrl: string - delay: number - index: number - mnemonic: string - recipientIndex: number - contractAddress: string - contractData: string - clientCount: number - reuseClient: boolean - maxGasPrice: number - totalTxGas: number - testMode: string -} - -export const builder = () => { - return yargs - .option('blockscout-measure-percent', { - type: 'number', - description: - 'Percent of transactions to measure the time it takes for blockscout to process a transaction. Should be in the range of [0, 100]', - default: 100, - }) - .option('blockscout-url', { - type: 'string', - description: - 'URL of blockscout used for measuring the time for transactions to be indexed by blockscout', - }) - .option('delay', { - type: 'number', - description: 'Delay between sending transactions in milliseconds', - default: 10000, - }) - .option('index', { - type: 'number', - description: - 'Index of the load test account to send transactions from. Used to generate account address', - }) - .option('recipient-index', { - type: 'number', - description: - 'Index of the load test account to send transactions to. Used to generate account address', - default: 0, - }) - .options('contract-address', { - type: 'string', - description: `Contract Address to send to when using test mode: ${TestMode.ContractCall}`, - default: '', - }) - .options('contract-data', { - type: 'string', - description: `Data to send to when using test mode: ${TestMode.ContractCall}`, - default: '', - }) - .options('mnemonic', { - type: 'string', - description: 'Mnemonic used to generate account addresses', - demand: 'A mnemonic must be provided', - }) - .options('client-count', { - type: 'number', - description: `Number of clients to simulate, must not exceed ${MAX_LOADTEST_THREAD_COUNT}`, - default: 1, - }) - .check((argv) => argv['client-count'] <= MAX_LOADTEST_THREAD_COUNT) - .options('reuse-client', { - type: 'boolean', - description: 'Use the same client for all the threads/accounts', - default: false, - }) - .options('max-gas-price', { - type: 'number', - description: 'Max gasPrice to use for transactions', - default: 0, - }) - .options('total-tx-gas', { - type: 'number', - description: 'Gas Target when using data transfers', - default: 500000, - }) - .options('test-mode', { - type: 'string', - description: - 'Load test mode: mixed transaction types, big calldatas, simple transfers paid in CELO, transfers paid in cUSD, or contract calls', - choices: [ - TestMode.Mixed, - TestMode.Data, - TestMode.Transfer, - TestMode.StableTransfer, - TestMode.ContractCall, - ], - default: TestMode.Mixed, - }) -} - -export const handler = async (argv: SimulateClientArgv) => { - for (let thread = 0; thread < argv.clientCount; thread++) { - const senderIndex = getIndexForLoadTestThread(argv.index, thread) - const recipientIndex = getIndexForLoadTestThread(argv.recipientIndex, thread) - const senderPK = generatePrivateKey( - argv.mnemonic, - AccountType.LOAD_TESTING_ACCOUNT, - senderIndex - ) - const recipientAddress = generateAddress( - argv.mnemonic, - AccountType.LOAD_TESTING_ACCOUNT, - recipientIndex - ) - - const web3ProviderPort = argv.reuseClient ? 8545 : 8545 + thread - - console.log( - `PK for sender index ${argv.index} thread ${thread}, final index ${senderIndex}: ${senderPK}` - ) - console.log( - `Account for recipient index ${argv.recipientIndex} thread ${thread}, final index ${recipientIndex}: ${recipientAddress}` - ) - console.log(`web3ProviderPort for thread ${thread}: ${web3ProviderPort}`) - - // tslint:disable-next-line: no-floating-promises - simulateClient( - senderPK, - recipientAddress, - argv.contractAddress, - argv.contractData, - argv.delay, - argv.blockscoutUrl, - argv.blockscoutMeasurePercent, - argv.index, - argv.testMode as TestMode, - thread, - new BigNumber(argv.maxGasPrice), - argv.totalTxGas, - `http://127.0.0.1:${web3ProviderPort}` - ) - } -} diff --git a/packages/celotool/src/cmds/geth/start.ts b/packages/celotool/src/cmds/geth/start.ts deleted file mode 100644 index 9273ceabb..000000000 --- a/packages/celotool/src/cmds/geth/start.ts +++ /dev/null @@ -1,298 +0,0 @@ -/* tslint:disable: no-console */ -import { readFileSync } from 'fs' -import { addCeloGethMiddleware } from 'src/lib/utils' -import yargs from 'yargs' -import { - AccountType, - getPrivateKeysFor, - getValidatorsInformation, - privateKeyToPublicKey, -} from '../../lib/generate_utils' -import { getEnodeAddress, migrateContracts, runGethNodes } from '../../lib/geth' -import { GethInstanceConfig } from '../../lib/interfaces/geth-instance-config' -import { GethRunConfig } from '../../lib/interfaces/geth-run-config' -import { GethArgv } from '../geth' - -export const command = 'start' -export const describe = 'command for running geth' - -interface StartArgv extends GethArgv { - networkId: string - syncMode: string - mining: boolean - blockTime: number - churritoBlock: number - donutBlock: number - port: number - rpcport: number - wsport: number - verbosity: number - verbose: boolean - instances: number - migrate: boolean - migrateTo: number - migrationOverrides: string - monorepoDir: string - purge: boolean - withProxy: boolean - ethstats: string - mnemonic: string - initialAccounts: string -} - -// hardForkBlockCoercer parses a hard fork activation block as follows: -// "null" => no activation -// "42" => activate at block 42 (and likewise for other numbers >= 0) -const hardForkBlockCoercer = (arg: string) => { - if (arg === 'null') { - return undefined - } else { - const value = parseInt(arg, 10) - if (typeof value === 'number' && value >= 0) { - return value - } else { - throw new Error(`Invalid value for hard fork activation block: '${arg}'`) - } - } -} - -export const builder = (argv: yargs.Argv) => { - return addCeloGethMiddleware(argv) - .option('network-id', { - type: 'string', - description: 'network id', - default: '1101', - }) - .option('sync-mode', { - choices: ['full', 'fast', 'light', 'ultralight', 'lightest'], - default: 'full', - }) - .option('mining', { - type: 'boolean', - description: 'Is mining enabled', - default: false, - }) - .option('port', { - type: 'number', - description: 'Port', - default: 30303, - }) - .option('rpcport', { - type: 'number', - description: 'HTTP-RPC server listening port', - default: 8545, - }) - .option('wsport', { - type: 'number', - description: 'WS-RPC server listening port', - default: 8546, - }) - .option('instances', { - type: 'number', - description: 'Number of instances to run', - default: 1, - }) - .option('with-proxy', { - type: 'boolean', - description: 'Start with proxy in front', - default: false, - }) - .option('verbosity', { - type: 'number', - description: 'Geth Verbosity level', - default: 5, - }) - .option('verbose', { - type: 'boolean', - description: 'Command verbosity flag', - default: false, - }) - .option('purge', { - type: 'boolean', - description: 'This will purge the data directory before starting.', - default: false, - }) - .option('ethstats', { - type: 'string', - description: 'address of the ethstats server', - }) - .option('mnemonic', { - type: 'string', - description: 'seed phrase to use for private key generation', - default: - 'jazz ripple brown cloth door bridge pen danger deer thumb cable prepare negative library vast', - }) - .option('blockTime', { - type: 'number', - description: 'Block Time', - default: 1, - }) - .option('churritoBlock', { - type: 'string', - coerce: hardForkBlockCoercer, - description: 'Churrito hard fork activation block number (use "null" for no activation)', - default: '0', - }) - .option('donutBlock', { - type: 'string', - coerce: hardForkBlockCoercer, - description: 'Donut hard fork activation block number (use "null" for no activation)', - default: '0', - }) - .option('migrate', { - type: 'boolean', - description: 'Migrate contracts', - default: false, - implies: 'monorepo-dir', - }) - .option('migrateTo', { - type: 'number', - description: 'Migrate contracts to level x', - implies: 'monorepo-dir', - }) - .option('migration-overrides', { - type: 'string', - description: 'Path to JSON file containing migration overrides', - implies: 'migrate', - }) - .option('monorepo-dir', { - type: 'string', - description: 'Directory of the mono repo', - }) - .option('initial-accounts', { - type: 'string', - description: - 'Path to JSON file containing accounts to place in the alloc property of the genesis.json file', - }) -} - -export const handler = async (argv: StartArgv) => { - const verbosity = argv.verbosity - const verbose = argv.verbose - - const networkId = parseInt(argv.networkId, 10) - const syncMode = argv.syncMode - const blockTime = argv.blockTime - const churritoBlock = argv.churritoBlock - const donutBlock = argv.donutBlock - - const port = argv.port - const rpcport = argv.rpcport - const wsport = argv.wsport - - const mining = argv.mining - const network = 'local' - const instances = argv.instances - const mnemonic = argv.mnemonic - const migrate = argv.migrate - const migrateTo = argv.migrateTo - const initialAccounts = argv.initialAccounts - ? JSON.parse(readFileSync(argv.initialAccounts).toString()) - : {} - const migrationOverrides = argv.migrationOverrides - ? JSON.parse(readFileSync(argv.migrationOverrides).toString()) - : {} - const monorepoDir = argv.monorepoDir - - const purge = argv.purge - const withProxy = argv.withProxy - - const ethstats = argv.ethstats - - const gethConfig: GethRunConfig = { - runPath: argv.dataDir, - keepData: !purge, - repository: { path: argv.gethDir }, - verbosity, - networkId, - migrate, - migrateTo, - migrationOverrides, - network, - instances: [], - genesisConfig: { - blockTime, - epoch: 17280, - initialAccounts, - churritoBlock, - donutBlock, - }, - } - - const validators = getValidatorsInformation(mnemonic, instances) - - const validatorPrivateKeys = getPrivateKeysFor(AccountType.VALIDATOR, mnemonic, instances) - - const proxyPrivateKeys = getPrivateKeysFor(AccountType.PROXY, mnemonic, instances) - - for (let x = 0; x < instances; x++) { - const node: GethInstanceConfig = { - name: `${x}-node`, - validating: mining, - syncmode: syncMode, - ethstats, - privateKey: validatorPrivateKeys[x], - port: port + x, - rpcport: rpcport + x * 2, - wsport: wsport + x * 2, - minerValidator: validators[x].address, - } - - let proxy: GethInstanceConfig | null = null - - if (withProxy) { - proxy = { - name: `${x}-proxy`, - validating: false, - isProxy: true, - syncmode: syncMode, - ethstats, - privateKey: proxyPrivateKeys[x], - port: port + x + 1000, - proxyport: port + x + 333, - rpcport: rpcport + x * 2 + 1000, - wsport: wsport + x * 2 + 1000, - } - - proxy.proxiedValidatorAddress = validators[x].address - proxy.proxy = validators[x].address - proxy.isProxy = true - - node.isProxied = true - node.proxyAllowPrivateIp = true - node.proxies = [ - getEnodeAddress(privateKeyToPublicKey(proxyPrivateKeys[x]), '127.0.0.1', proxy.proxyport!), - getEnodeAddress(privateKeyToPublicKey(validatorPrivateKeys[x]), '127.0.0.1', node.port), - ] - } - - gethConfig.instances.push(node) - if (proxy) { - gethConfig.instances.push(proxy) - } - } - - await runGethNodes({ - gethConfig, - validators, - verbose, - }) - - if (gethConfig.migrate || gethConfig.migrateTo) { - const attestationKeys = getPrivateKeysFor(AccountType.ATTESTATION, mnemonic, instances) - - console.log('Migrating contracts (this will take a long time) ...') - - await migrateContracts( - monorepoDir, - validatorPrivateKeys, - attestationKeys, - validators.map((x) => x.address), - gethConfig.migrateTo, - gethConfig.migrationOverrides, - verbose - ) - - console.log('... done migrating contracts!') - } -} diff --git a/packages/celotool/src/cmds/geth/static_nodes.ts b/packages/celotool/src/cmds/geth/static_nodes.ts deleted file mode 100644 index 0c311606b..000000000 --- a/packages/celotool/src/cmds/geth/static_nodes.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { addCeloEnvMiddleware, CeloEnvArgv } from 'src/lib/env-utils' -import { getEnodesWithExternalIPAddresses, writeStaticNodes } from 'src/lib/geth' -import yargs from 'yargs' - -export const command = 'static-nodes' - -export const describe = - 'command for creating static-nodes.json file containing nodes of transaction nodes in an environment' - -interface StaticNodesArgv extends CeloEnvArgv { - outputDir: string - outputFileName: string | null -} - -export const builder = (argv: yargs.Argv) => { - return addCeloEnvMiddleware(argv) - .option('output-dir', { - type: 'string', - description: 'path to directory where file with enodes addresses will be stored', - demand: 'Please specify the directory where to save the generated file', - }) - .option('output-file-name', { - type: 'string', - default: null, - alias: 'o', - description: - 'output file name | if not specified then {ENV_NAME}_static-nodes.json will be used', - }) -} - -export const handler = async (argv: StaticNodesArgv) => { - await switchToClusterFromEnv(argv.celoEnv, false) - - const namespace = argv.celoEnv - const outputDirPath = argv.outputDir - const outputFileName = argv.outputFileName - - await getEnodesWithExternalIPAddresses(namespace).then((enodes) => { - writeStaticNodes( - enodes, - outputDirPath, - outputFileName ? outputFileName : `${namespace}_static-nodes.json` - ) - }) -} diff --git a/packages/celotool/src/cmds/geth/trace.ts b/packages/celotool/src/cmds/geth/trace.ts deleted file mode 100644 index 286c6a2be..000000000 --- a/packages/celotool/src/cmds/geth/trace.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { getBlockscoutUrl } from 'src/lib/endpoints' -import { addCeloEnvMiddleware, CeloEnvArgv } from 'src/lib/env-utils' -import { checkGethStarted, getWeb3AndTokensContracts, traceTransactions } from 'src/lib/geth' -import yargs from 'yargs' -import { GethArgv } from '../geth' - -export const command = 'trace ' - -export const describe = 'command for tracing tokens transfers between accounts' - -interface TraceArgv extends GethArgv, CeloEnvArgv { - address1: string - address2: string -} - -export const builder = (argv: yargs.Argv) => { - return addCeloEnvMiddleware(argv) - .option('data-dir', { - type: 'string', - description: 'path to datadir', - demand: 'Please, specify geth datadir', - }) - .positional('address1', { - description: 'sender address', - }) - .positional('address2', { - description: 'recipient address', - }) -} - -const sleep = (ms: number) => { - return new Promise((resolve: any) => setTimeout(resolve, ms)) -} - -export const handler = async (argv: TraceArgv) => { - const dataDir = argv.dataDir - const address1 = argv.address1 - const address2 = argv.address2 - - checkGethStarted(dataDir) - - let iterations = 70 - let web3AndContracts = null - outerwhile: while (iterations-- > 0) { - try { - web3AndContracts = await getWeb3AndTokensContracts() - const { kit: kit1 } = web3AndContracts - const latestBlock = await kit1.connection.getBlock('latest') - if (latestBlock.number === 0) { - throw new Error('Latest block is zero') - } else { - break outerwhile - } - } catch (ignored: any) { - console.warn(ignored.toString()) - if (iterations === 0) { - console.error('Geth start error') - } - await sleep(1000) - } - } - - if (iterations <= 0) { - console.warn('Can not wait for geth to sync') - console.error('bad start') - process.exit(1) - } - - const { kit, goldToken, stableToken } = web3AndContracts! - - // This is needed to turn off debug logging which is made in `sendTransaction` - // and needed only for mobile client. - console.debug = () => { - // empty - } - - await traceTransactions( - kit, - goldToken, - // @ts-ignore - TODO: remove when web3 upgrade completed everywhere - stableToken, - [address1, address2], - getBlockscoutUrl(argv.celoEnv) - ) -} diff --git a/packages/celotool/src/cmds/geth/transfer.ts b/packages/celotool/src/cmds/geth/transfer.ts deleted file mode 100644 index 376ced124..000000000 --- a/packages/celotool/src/cmds/geth/transfer.ts +++ /dev/null @@ -1,69 +0,0 @@ -import BigNumber from 'bignumber.js' -import { checkGethStarted, getWeb3AndTokensContracts, transferERC20Token } from 'src/lib/geth' -import yargs from 'yargs' -import { GethArgv } from '../geth' - -export const command = 'transfer ' - -export const describe = 'command for transfering tokens between accounts' - -const CELO_GOLD = 'cGLD' -const CELO_DOLLARS = 'cUSD' - -interface TransferArgv extends GethArgv { - senderAddress: string - receiverAddress: string - token: string - amount: string - password: string -} - -export const builder = (argv: yargs.Argv) => { - return argv - .option('data-dir', { - type: 'string', - description: 'path to datadir', - demand: 'Please, specify geth datadir', - }) - .positional('senderAddress', { - description: 'sender address', - }) - .positional('receiverAddress', { - description: 'recipient address', - }) - .positional('token', { - choices: [CELO_GOLD, CELO_DOLLARS], - }) - .positional('amount', { - description: 'amount to transfer', - }) - .option('password', { - type: 'string', - description: 'sender account password', - default: '', - }) -} - -export const handler = async (argv: TransferArgv) => { - const dataDir = argv.dataDir - const senderAddress = argv.senderAddress - const receiverAddress = argv.receiverAddress - const tokenType = argv.token - const amount = argv.amount - const password = argv.password - - checkGethStarted(dataDir) - - const { kit, goldToken, stableToken } = await getWeb3AndTokensContracts() - - const transferrableToken = tokenType === CELO_GOLD ? goldToken : stableToken - - await transferERC20Token( - kit, - transferrableToken, - senderAddress, - receiverAddress, - new BigNumber(amount), - password - ) -} diff --git a/packages/celotool/src/cmds/local_testnet.ts b/packages/celotool/src/cmds/local_testnet.ts deleted file mode 100644 index a44b83d90..000000000 --- a/packages/celotool/src/cmds/local_testnet.ts +++ /dev/null @@ -1,384 +0,0 @@ -import { newKit } from '@celo/contractkit' -import { extend, range } from 'lodash' -import { getHooks, sleep } from 'src/e2e-tests/utils' -import { privateKeyToPublicKey } from 'src/lib/generate_utils' -import { GethInstanceConfig } from 'src/lib/interfaces/geth-instance-config' -import { GethRunConfig } from 'src/lib/interfaces/geth-run-config' -import Web3 from 'web3' -import { Admin } from 'web3-eth-admin' -import yargs from 'yargs' - -const Account: any = require('eth-lib/lib/account') - -export const command = 'local-testnet' -export const describe = `Command to run a local testnet of geth instances. - -Running this command will create a number of geth nodes, connect them together to form a network, -and run smart contract migrations to initialize the core protocols. When this is complete, it will -open a NodeJS console with some preloaded objects to facilitate interactions with the test network. -Exiting this console will kill all running geth instances and exit. - -Examples: -* local-testnet -* local-testnet --local-geth ~/code/celo-blockchain -* local-testnet --validators 5 --proxies 3 --bootnode -* local-testnet --tx-nodes 2 --light-clients 3 -* local-testnet --migrate-to 19 --migration-override '{ "lockedGold": { "unlockingPeriod": 30 } }' -* local-testnet --no-migrate --genesis-override '{ "blockTime": 3, "epoch": 50 }' - -Network makeup is configured the --validators, --tx-nodes, --light-clients, and --lightest-client -flags. These flags will add the corresponding nodes to the network. - -A NodeJS REPL is provided to conveniently interact with the created network. A number of global -variables are defined with useful values including { - Web3 (Imported 'web3' module) - Admin (Imported 'web3-eth-admin' module) - testnet: GethRunConfig (Configuration values for the tesnet) - [nodeType][index] (e.g. validator0, txNode2): { - web3: Web3 (A web3 object connected to the node over RPC) - kit: ContractKit (A contractkit object connected to the node over RPC) - admin: Admin (An Admin object connected to the node over RPC) - config: GethInstanceConfig (Configuration values for the node) - kill(signal?: string): (Send a signal, default SIGTERM, to the node. e.g. SIGINT, SIGSTOP) - } -} - -Tip: Export NODE_OPTIONS="--experimental-repl-await" in your terminal to natively use await. - -When the network is created without a bootnode, all nodes will be connected as follows: -* Proxy nodes are connected to their validators, other proxies and unproxied validators. -* Unproxied validator nodes are connected to all other proxies and unproxied validators. -* Transaction nodes are connected to proxies and unproxied validators and other transaction nodes. -* Light clients are connected to all transaction nodes. - -If the network is started with the --bootnode flag, a bootnode will be created and all nodes will be -connected to it, rather than each other directly. - -By default, the celo-blockchain repository will be cloned to a temporary location and built from -master to produce the geth binary to run for each node. The --branch flag can be used to control -which branch is built in the cloned repository. Alternatively, a existing repository can be used -by specifying the --local-geth flag as the path to that repository root.` - -interface LocalTestnetArgs { - localgeth?: string - keepdata?: boolean - branch?: string - bootnode: boolean - validators: number - proxies: number - txnodes: number - lightclients: number - lightestclients: number - migrate: boolean - migrateTo: number - instances: string - genesisOverride: string - migrationOverride: string -} - -export const builder = (argv: yargs.Argv) => { - return argv - .option('local-geth', { - type: 'string', - description: 'Local path to celo-blockchain repository.', - alias: ['localGeth', 'localgeth'], - }) - .option('keep-data', { - type: 'boolean', - decription: 'Keep the data directory from any previous runs.', - alias: ['keepData', 'keepdata'], - }) - .option('branch', { - type: 'string', - description: 'Branch name for remote celo-blockchain repository.', - }) - .option('bootnode', { - type: 'boolean', - allowNo: true, - description: 'Create a bootnode and connect all nodes to it instead of to each other.', - }) - .option('validators', { - type: 'number', - description: 'Number of validator nodes to create.', - default: 1, - }) - .option('proxies', { - type: 'number', - description: 'Number of proxy nodes to create; assigned to the first n validators.', - default: 0, - }) - .option('tx-nodes', { - type: 'number', - description: 'Number of transaction (i.e. non-validating full nodes) nodes to create.', - default: 0, - alias: ['txnodes', 'txNodes'], - }) - .option('light-clients', { - type: 'number', - description: 'Number of light sync nodes to create.', - default: 0, - alias: ['lightClients', 'lightclients'], - }) - .option('lightest-clients', { - type: 'number', - description: 'Number of lightest sync nodes to create.', - default: 0, - alias: ['lightestClients', 'lightestclients'], - }) - .option('migrate', { - type: 'boolean', - description: 'Whether migrations should be run.', - default: true, - allowNo: true, - }) - .option('migrate-to', { - type: 'number', - description: 'Maximum migration number to run. Defaults to running all migrations.', - alias: ['migrateTo', 'migrateto'], - }) - .option('instances', { - type: 'string', - description: 'Manually enter a GethInstanceConfig[] json blob to add to the config.', - default: '[]', - }) - .option('genesis-override', { - type: 'string', - description: 'Genesis configuration overrides as a GenesisConfig JSON blob.', - default: '{}', - alias: ['genesisOverride', 'genesisoverride'], - }) - .option('migration-override', { - type: 'string', - description: 'Migration configuration overrides as a JSON blob.', - default: '{}', - alias: ['migrationOverride', 'migrationoverride'], - }) -} - -async function repl(config: GethRunConfig) { - const session = require('repl').start() - const formatName = (name: string) => - name - .split('-') - .map((token, i) => (i === 0 ? token[0] : token[0].toUpperCase()) + token.slice(1)) - .join('') - - extend(session.context, { - Web3, - Admin, - testnet: config, - ...config.instances.reduce( - (o, instance) => ({ - ...o, - [formatName(instance.name)]: { - web3: new Web3(getRpcUrl(instance)), - kit: newKit(getRpcUrl(instance)), - admin: new Admin(getRpcUrl(instance)), - config: instance, - kill: (signal?: string) => { - if (!instance.pid) { - throw new Error(`no pid registered for instance ${instance.name}`) - } - process.kill(instance.pid, signal) - }, - }, - }), - {} - ), - }) - - // Wait for the REPL to exit. - let exited = false - const exitHandler = () => { - exited = true - } - session.on('exit', exitHandler) - while (!exited) { - await sleep(0.1) - } - session.removeListener('exit', exitHandler) -} - -function bootnodeConfigs(count: number): GethInstanceConfig[] { - return range(count).map((i) => ({ - name: `bootnode-${i}`, - lightserv: false, - syncmode: 'full', - nodekey: generatePrivateKey(), - port: 0, - })) -} - -function validatorConfigs(count: number, proxyCount: number = 0): GethInstanceConfig[] { - const validators: GethInstanceConfig[] = range(count).map((i) => ({ - name: `validator-${i}`, - validating: true, - syncmode: 'full', - isProxied: i < proxyCount, - proxy: i < proxyCount ? `proxy-${i}` : undefined, - proxyAllowPrivateIp: i < proxyCount ? true : undefined, - port: 0, - })) - const proxies: GethInstanceConfig[] = range(proxyCount).map((i) => ({ - name: `proxy-${i}`, - syncmode: 'full', - isProxy: true, - port: 0, - })) - return validators.concat(proxies) -} - -function txNodeConfigs(count: number): GethInstanceConfig[] { - return range(count).map((i) => ({ - name: `tx-node-${i}`, - lightserv: true, - syncmode: 'full', - port: 0, - })) -} - -function lightClientConfigs(count: number): GethInstanceConfig[] { - return range(count).map((i) => ({ - name: `light-client-${i}`, - syncmode: 'light', - port: 0, - })) -} - -function lightestClientConfigs(count: number): GethInstanceConfig[] { - return range(count).map((i) => ({ - name: `lightest-client-${i}`, - syncmode: 'lightest', - port: 0, - })) -} - -// Populate network information in instance configs. -function populateConnectionInfo(configs: GethInstanceConfig[]): GethInstanceConfig[] { - // Choose ports for each instance. - for (const [i, config] of configs.entries()) { - if (!config.port) { - config.port = 30303 + 2 * i - } - if (config.isProxy && !config.proxyport) { - config.proxyport = 30503 + 2 * i - } - if (!config.rpcport && !config.wsport) { - config.rpcport = 8545 + 2 * i - config.wsport = 8546 + 2 * i - } - } - - // If a bootnode is provided, populate bootnode information in other nodes. - const bootnodes = configs.filter((config) => /bootnode/.test(config.name)) - if (bootnodes.length > 0) { - // Only one in-use bootnode is supported. - const bootnode = bootnodes[0] - for (const config of configs) { - if (config.name === bootnode.name || config.isProxied) { - continue - } - config.bootnodeEnode = getEnodeUrl(bootnode) - } - } - - return configs -} - -function getEnodeUrl(config: GethInstanceConfig) { - if (!config.nodekey) { - throw new Error('cannot get the enode url from a config without a nodekey') - } - return `enode://${privateKeyToPublicKey(config.nodekey)}@localhost:${config.port}` -} - -function generatePrivateKey() { - return Account.create(Web3.utils.randomHex(32)).privateKey.replace('0x', '') -} - -function getRpcUrl(config: GethInstanceConfig) { - return `${config.wsport ? 'ws' : 'http'}://localhost:${config.wsport || config.rpcport}` -} - -function getAdmin(config: GethInstanceConfig) { - if (!config.wsport && !config.rpcport) { - throw new Error('connot connect to admin interface for config without port') - } - return new Admin(getRpcUrl(config)) -} - -async function getEnode(config: GethInstanceConfig) { - const admin = getAdmin(config) - return (await admin.getNodeInfo()).enode -} - -async function connectToEnodes(config: GethInstanceConfig, enodes: string[]) { - const admin = getAdmin(config) - await Promise.all(enodes.map((enode) => admin.addPeer(enode))) -} - -async function connectNodes(configs: GethInstanceConfig[]) { - // Connect tx nodes to validators and other tx nodes. - const validators = configs.filter( - (config) => (config.validating && !config.isProxied) || config.isProxy - ) - const validatorEnodes = await Promise.all(validators.map(getEnode)) - const txNodes = configs.filter((config) => !config.validating && config.syncmode === 'full') - const txNodeEnodes = await Promise.all(txNodes.map(getEnode)) - await Promise.all( - txNodes.map((txNode) => connectToEnodes(txNode, validatorEnodes.concat(txNodeEnodes))) - ) - - // Connect light clients to tx nodes. - const lightClients = configs.filter((config) => ['light', 'lightest'].includes(config.syncmode)) - if (lightClients.length > 0 && txNodeEnodes.length === 0) { - throw new Error('connecting light clients to the network requires at least one tx-node') - } - await Promise.all(lightClients.map((lightClient) => connectToEnodes(lightClient, txNodeEnodes))) -} - -export const handler = async (argv: LocalTestnetArgs) => { - const repoPath = argv.localgeth || '/tmp/geth' - - const gethConfig: GethRunConfig = { - network: 'local', - networkId: 1101, - runPath: '/tmp/e2e', - keepData: argv.keepdata, - migrate: argv.migrate, - migrateTo: argv.migrate ? argv.migrateTo : undefined, - instances: populateConnectionInfo([ - ...validatorConfigs(argv.validators, argv.proxies), - ...txNodeConfigs(argv.txnodes), - ...lightClientConfigs(argv.lightclients), - ...lightestClientConfigs(argv.lightestclients), - ...bootnodeConfigs(argv.bootnode ? 1 : 0), - ...JSON.parse(argv.instances), - ]), - repository: { - path: repoPath, - branch: argv.branch, - remote: !argv.localgeth, - }, - genesisConfig: JSON.parse(argv.genesisOverride), - migrationOverrides: JSON.parse(argv.migrationOverride), - } - const hooks = getHooks(gethConfig) - await hooks.initialize() - - if (!argv.bootnode) { - await connectNodes(gethConfig.instances) - } - - console.info(`Local testnet is online with ${gethConfig.instances.length} nodes:`) - for (const instance of gethConfig.instances) { - console.info( - ` * ${instance.name} (pid:${instance.pid}) is listening on ${getRpcUrl(instance)}` - ) - } - console.info('\nPress CTRL+D to quit') - - await repl(gethConfig) - await hooks.after() - process.exit(0) -} diff --git a/packages/celotool/src/cmds/port_forward.ts b/packages/celotool/src/cmds/port_forward.ts deleted file mode 100644 index f60ce0a92..000000000 --- a/packages/celotool/src/cmds/port_forward.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { addCeloEnvMiddleware, CeloEnvArgv } from 'src/lib/env-utils' -import { defaultPortsString, portForward } from 'src/lib/port_forward' -import yargs from 'yargs' -export const command = 'port-forward' - -export const describe = 'command for port-forwarding to a specific network' - -interface PortForwardArgv extends CeloEnvArgv { - component: string - ports: string -} - -export const builder = (argv: yargs.Argv) => { - return addCeloEnvMiddleware(argv) - .option('component', { - type: 'string', - description: 'K8s component name to forward to', - }) - .option('ports', { - type: 'string', - description: 'Ports to forward: space separated srcport:dstport string', - default: defaultPortsString, - }) -} - -export const handler = async (argv: PortForwardArgv) => { - await switchToClusterFromEnv(argv.celoEnv, false, true) - await portForward(argv.celoEnv, argv.component, argv.ports) -} diff --git a/packages/celotool/src/cmds/restore.ts b/packages/celotool/src/cmds/restore.ts deleted file mode 100644 index 253ba0fc7..000000000 --- a/packages/celotool/src/cmds/restore.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { execCmdWithExitOnFailure } from 'src/lib/cmd-utils' -import { addCeloEnvMiddleware, CeloEnvArgv } from 'src/lib/env-utils' -import yargs from 'yargs' - -export const command = 'restore' - -export const describe = "command for restoring a miner's persistent volume (PVC) from snapshot" - -interface RestoreArgv extends CeloEnvArgv { - minername: string - snapshotname: string -} - -export const builder = (argv: yargs.Argv) => { - return addCeloEnvMiddleware(argv) - .option('minername', { - type: 'string', - description: 'Name of the miner node', - demand: 'Please specify the miner node to restore, eg. gethminer1', - }) - .option('snapshotname', { - type: 'string', - description: 'Name of the snapshot', - demand: 'Name of the snapshot (from gcloud compute snapshots list)', - }) -} - -export const handler = async (argv: RestoreArgv) => { - await switchToClusterFromEnv(argv.celoEnv, true, true) - - const minerName = argv.minername - // In the future, we can make this configurable. - // const zone = 'us-west1-a' - // In the future, we can make this configurable. - const clusterName = 'celo-networks-dev' - const diskType = 'pd-ssd' - const namespace = argv.celoEnv - const pvc = `${namespace}-${minerName}-pvc` - // TODO: figure out how to make this confgurable - - const getPVCNameCommand = `kubectl get persistentvolumeclaim ${pvc} --namespace ${namespace} -o=jsonpath={.spec.volumeName}` - const pvcId = (await execCmdWithExitOnFailure(getPVCNameCommand))[0] - const pvcFullId = `gke-${clusterName}--${pvcId}` - console.debug(`PVC name is ${pvcFullId}`) - - // If the disk already exists, then this command will fail and in that case, - // the disk has to be deleted first via `gcloud compute disks delete ${pvcFullId}` - // That itself requires that the miner node be stopped. - // For now, this step is intentionally manual. - // When we encounter a real world use-case of restore, we can decide whether to automate this or not. - const restoreSnapshotCmd = `gcloud compute disks create ${pvcFullId} --source-snapshot=${argv.snapshotname} --type ${diskType}` - await execCmdWithExitOnFailure(restoreSnapshotCmd) - // const gcloudSnapshotsUrl = 'https://console.cloud.google.com/compute/snapshots' - // console.info(`Snapshot \"${snapshotName}\" can be seen at ${gcloudSnapshotsUrl}`) -} diff --git a/packages/celotool/src/cmds/switch.ts b/packages/celotool/src/cmds/switch.ts deleted file mode 100644 index b2937e749..000000000 --- a/packages/celotool/src/cmds/switch.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { addCeloEnvMiddleware, CeloEnvArgv } from 'src/lib/env-utils' -import yargs from 'yargs' - -export const command = 'switch' - -export const describe = 'command for switching to a particular environment' - -// sets environment variables from .env -export const builder = (argv: yargs.Argv) => addCeloEnvMiddleware(argv) - -export const handler = async (argv: CeloEnvArgv) => { - await switchToClusterFromEnv(argv.celoEnv, false, true) -} diff --git a/packages/celotool/src/cmds/transactions.ts b/packages/celotool/src/cmds/transactions.ts deleted file mode 100644 index f3aa090a3..000000000 --- a/packages/celotool/src/cmds/transactions.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { addCeloEnvMiddleware, CeloEnvArgv } from 'src/lib/env-utils' -import { Argv } from 'yargs' - -export const command = 'transactions ' - -export const describe = 'commands for reading transaction data' - -export type TransactionsArgv = CeloEnvArgv - -export function builder(argv: Argv) { - return addCeloEnvMiddleware(argv).commandDir('transactions', { extensions: ['ts'] }) -} - -export function handler() { - // empty -} diff --git a/packages/celotool/src/cmds/transactions/describe.ts b/packages/celotool/src/cmds/transactions/describe.ts deleted file mode 100644 index 9c6c70c93..000000000 --- a/packages/celotool/src/cmds/transactions/describe.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { newKitFromWeb3 } from '@celo/contractkit' -import { newBlockExplorer } from '@celo/explorer/lib/block-explorer' -import { newLogExplorer } from '@celo/explorer/lib/log-explorer' -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { getFornoUrl } from 'src/lib/endpoints' -import Web3 from 'web3' -import yargs from 'yargs' -import { TransactionsArgv } from '../transactions' -export const command = 'describe ' - -export const describe = 'fetch a transaction, attempt parsing and print it out to STDOUT' - -interface DescribeArgv extends TransactionsArgv { - transactionHash: string -} - -export const builder = (argv: yargs.Argv) => { - return argv.positional('transactionHash', { - description: 'The hash of the transaction', - }) -} - -export const handler = async (argv: DescribeArgv) => { - await switchToClusterFromEnv(argv.celoEnv, false) - - const web3 = new Web3(getFornoUrl(argv.celoEnv)) - const kit = await newKitFromWeb3(web3) - const blockExplorer = await newBlockExplorer(kit) - const logExplorer = await newLogExplorer(kit) - const transaction = await web3.eth.getTransaction(argv.transactionHash) - const receipt = await web3.eth.getTransactionReceipt(argv.transactionHash) - - if (process.env.CELOTOOL_VERBOSE === 'true') { - console.info('Raw Transaction Data:') - console.info(transaction) - - console.info('Raw Transaction Receipt') - console.info(receipt) - } - - const parsedTransaction = await blockExplorer.tryParseTx(transaction) - - if (parsedTransaction === null) { - return - } - - console.info('Parsed Transaction Data') - console.info(parsedTransaction) - - if (receipt.logs) { - receipt.logs.forEach((log) => { - const parsedLog = logExplorer.tryParseLog(log) - - if (parsedLog === null) { - return - } - - console.info('Parsed Transaction Log') - console.info(parsedLog) - }) - } - - if (!receipt.status) { - console.info('Transaction reverted, attempting to recover revert reason ...') - - const called = await web3.eth.call( - { - data: transaction.input, - to: transaction.to ? transaction.to : undefined, - from: transaction.from, - }, - transaction.blockNumber! - ) - - if (called.startsWith('0x08c379a')) { - console.info('Revert reason is:') - console.info(web3.eth.abi.decodeParameter('string', '0x' + called.substring(10))) - } else { - console.info('Could not retrieve revert reason') - } - } -} diff --git a/packages/celotool/src/cmds/transactions/list.ts b/packages/celotool/src/cmds/transactions/list.ts deleted file mode 100644 index 930236e6b..000000000 --- a/packages/celotool/src/cmds/transactions/list.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { newKitFromWeb3 } from '@celo/contractkit' -import { BlockExplorer, newBlockExplorer } from '@celo/explorer/lib/block-explorer' -import { LogExplorer, newLogExplorer } from '@celo/explorer/lib/log-explorer' -import fetch from 'node-fetch' -import { CONTRACTS_TO_COPY, copyContractArtifacts, downloadArtifacts } from 'src/lib/artifacts' -import { getWeb3Client } from 'src/lib/blockchain' -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { getBlockscoutUrl } from 'src/lib/endpoints' -import Web3 from 'web3' -import yargs from 'yargs' -import { TransactionsArgv } from '../transactions' - -export const command = 'list
' - -export const describe = 'lists transactions to this address' - -interface ListArgv extends TransactionsArgv { - address: string -} - -export const builder = (argv: yargs.Argv) => { - return argv.positional('address', { - description: 'the address to search for', - }) -} - -export const handler = async (argv: ListArgv) => { - await switchToClusterFromEnv(argv.celoEnv, false) - - await downloadArtifacts(argv.celoEnv) - await copyContractArtifacts( - argv.celoEnv, - '../transaction-metrics-exporter/src/contracts', - CONTRACTS_TO_COPY - ) - - const web3 = await getWeb3Client(argv.celoEnv) - const blockscoutURL = getBlockscoutUrl(argv.celoEnv) - const kit = await newKitFromWeb3(web3) - const blockExplorer = await newBlockExplorer(kit) - const logExplorer = await newLogExplorer(kit) - const resp = await fetch( - `${blockscoutURL}/api?module=account&action=txlist&address=${argv.address}&sort=desc` - ) - const jsonResp = (await resp.json()) as any - - if (jsonResp.result === undefined) { - return - } - - for (const blockscoutTx of jsonResp.result) { - await fetchTx(web3, blockExplorer, logExplorer, blockscoutTx) - } - process.exit(0) -} - -async function fetchTx( - web3: Web3, - blockExplorer: BlockExplorer, - logExplorer: LogExplorer, - blockscoutTx: { hash: string; timeStamp: string } -) { - const transaction = await web3.eth.getTransaction(blockscoutTx.hash) - const receipt = await web3.eth.getTransactionReceipt(blockscoutTx.hash) - - const parsedTransaction = await blockExplorer.tryParseTx(transaction) - - if (parsedTransaction === null) { - console.info(`Unparsable Transaction: ${transaction.hash}`) - return - } - - console.info( - `${parsedTransaction.callDetails.contract}#${ - parsedTransaction.callDetails.function - }(${JSON.stringify(parsedTransaction.callDetails.paramMap)}) ${parsedTransaction.tx.hash}` - ) - - if (receipt.logs) { - receipt.logs.forEach((log) => { - try { - const parsedLog = logExplorer.tryParseLog(log) - - if (parsedLog === null) { - console.info(`\tParsed log is null for log "${log.address}"`) - return - } - - console.info(`\t${parsedLog.event}(${JSON.stringify(parsedLog.returnValues)})`) - } catch (e) { - console.error(`Error while parsing log ${log}`) - } - }) - } -} diff --git a/packages/celotool/src/cmds/unfreeze_contracts.ts b/packages/celotool/src/cmds/unfreeze_contracts.ts deleted file mode 100644 index 97492b5a9..000000000 --- a/packages/celotool/src/cmds/unfreeze_contracts.ts +++ /dev/null @@ -1,110 +0,0 @@ -/* tslint:disable no-console */ -import { ContractKit, newKitFromWeb3 } from '@celo/contractkit' -import { switchToClusterFromEnv } from 'src/lib/cluster' -import { addCeloEnvMiddleware, CeloEnvArgv } from 'src/lib/env-utils' -import { portForwardAnd } from 'src/lib/port_forward' -import Web3 from 'web3' -import yargs from 'yargs' - -export const command = 'unfreeze-contracts' - -export const describe = 'command for unfreezing epoch rewards and the exchange' - -interface UnfreezeContractsArgv extends CeloEnvArgv { - exchange: boolean - rewards: boolean - freeze: boolean - precheck: boolean - verify: boolean -} - -export const builder = (argv: yargs.Argv) => { - return addCeloEnvMiddleware(argv) - .option('exchange', { - type: 'boolean', - description: 'Affect the exchange', - default: true, - }) - .option('rewards', { - type: 'boolean', - description: 'Affect epoch rewards', - default: true, - }) - .option('freeze', { - type: 'boolean', - description: 'Freeze contracts instead of unfreezing', - default: false, - }) - .option('precheck', { - type: 'boolean', - description: 'Check the contract freeze status before continuing', - default: true, - }) - .option('verify', { - type: 'boolean', - description: 'Verify the contract freeze status after', - default: true, - }) -} - -export const handler = async (argv: UnfreezeContractsArgv) => { - await switchToClusterFromEnv(argv.celoEnv) - - const cb = async () => { - const web3: Web3 = new Web3('http://localhost:8545') - const kit: ContractKit = newKitFromWeb3(web3) - const account = (await kit.connection.getAccounts())[0] - console.log(`Using account: ${account}`) - kit.connection.defaultAccount = account - - const [exchange, epochRewards] = await Promise.all([ - argv.exchange ? kit._web3Contracts.getExchange() : null, - argv.rewards ? kit._web3Contracts.getEpochRewards() : null, - ]) - const freezerContract = await kit._web3Contracts.getFreezer() - - for (const [name, contract] of Object.entries({ exchange, epochRewards })) { - if (contract === null) { - continue - } - - const address = (contract as any)._address - if (argv.precheck) { - const frozen = await freezerContract.methods.isFrozen(address).call() - // console.debug(`${name}.frozen = ${frozen}`) - if (argv.freeze === frozen) { - console.error(`${name} is already ${argv.freeze ? 'frozen' : 'unfrozen'}. Skipping.`) - continue - } - } - - if (argv.freeze) { - console.info(`Sending freeze transaction to ${name} ...`) - await freezerContract.methods.freeze(address).send({ from: account }) - } else { - console.info(`Sending unfreeze transaction to ${name} ...`) - await freezerContract.methods.unfreeze(address).send({ from: account }) - } - - if (argv.verify) { - const frozen = await freezerContract.methods.isFrozen(address).call() - // console.debug(`${name}.frozen = ${frozen}`) - if (argv.freeze !== frozen) { - console.error( - `${name} is not ${argv.freeze ? 'frozen' : 'unfrozen'}. Something went wrong.` - ) - continue - } - console.info(`Succesfully ${argv.freeze ? 'froze' : 'unfroze'} ${name}`) - } - } - } - - try { - await portForwardAnd(argv.celoEnv, cb) - } catch (error) { - console.error(`Unable to ${argv.freeze ? 'freeze' : 'unfreeze'} contracts on ${argv.celoEnv}`) - console.error(error) - process.exit(1) - } -} diff --git a/packages/celotool/src/e2e-tests/blockchain_parameters_tests.ts b/packages/celotool/src/e2e-tests/blockchain_parameters_tests.ts deleted file mode 100644 index 3e4c77cd9..000000000 --- a/packages/celotool/src/e2e-tests/blockchain_parameters_tests.ts +++ /dev/null @@ -1,84 +0,0 @@ -// tslint:disable:no-console -import { ContractKit, newKitFromWeb3 } from '@celo/contractkit' -import { BlockchainParametersWrapper } from '@celo/contractkit/lib/wrappers/BlockchainParameters' -import { assert } from 'chai' -import Web3 from 'web3' -import { GethRunConfig } from '../lib/interfaces/geth-run-config' -import { getHooks, sleep } from './utils' - -const TMP_PATH = '/tmp/e2e' -const rpcURL = 'http://localhost:8545' - -describe('Blockchain parameters tests', function (this: any) { - this.timeout(0) - - let kit: ContractKit - let parameters: BlockchainParametersWrapper - - const gethConfig: GethRunConfig = { - migrate: true, - runPath: TMP_PATH, - keepData: false, - networkId: 1101, - network: 'local', - genesisConfig: { - churritoBlock: 0, - donutBlock: 0, - espressoBlock: 0, - }, - instances: [ - { - name: 'validator', - validating: true, - syncmode: 'full', - port: 30303, - rpcport: 8545, - }, - ], - } - - const hooks = getHooks(gethConfig) - - before(async function (this: any) { - this.timeout(0) - await hooks.before() - }) - - after(async function (this: any) { - this.timeout(0) - await hooks.after() - }) - - const validatorAddress: string = '0x47e172f6cfb6c7d01c1574fa3e2be7cc73269d95' - - const restartGeth = async () => { - // Restart the validator node - await hooks.restart() - - // TODO(mcortesi): magic sleep. without it unlockAccount sometimes fails - await sleep(2) - - kit = newKitFromWeb3(new Web3(rpcURL)) - - await kit.connection.web3.eth.personal.unlockAccount(validatorAddress, '', 1000) - parameters = await kit.contracts.getBlockchainParameters() - } - - describe('when running a node', () => { - before(async () => { - await restartGeth() - }) - it('block limit should have been set using governance', async () => { - this.timeout(0) - const res = await parameters.getBlockGasLimit() - assert.equal(0, res.comparedTo(13000000)) - }) - it('changing the block gas limit', async () => { - this.timeout(0) - await parameters.setBlockGasLimit(23000000).send({ from: validatorAddress }) - await sleep(2) - const res = await parameters.getBlockGasLimit() - assert.equal(0, res.comparedTo(23000000)) - }) - }) -}) diff --git a/packages/celotool/src/e2e-tests/cip35_tests.ts b/packages/celotool/src/e2e-tests/cip35_tests.ts deleted file mode 100644 index a93fb2bec..000000000 --- a/packages/celotool/src/e2e-tests/cip35_tests.ts +++ /dev/null @@ -1,507 +0,0 @@ -// tslint:disable:no-console -import { CeloTx } from '@celo/connect' -import { ContractKit, newKitFromWeb3 } from '@celo/contractkit' -import { privateKeyToAddress } from '@celo/utils/lib/address' -import * as ejsRlp from '@ethereumjs/rlp' -import * as ejsUtil from '@ethereumjs/util' -import BigNumber from 'bignumber.js' -import { assert } from 'chai' -import { keccak256 } from 'ethereum-cryptography/keccak' -import { toHex } from 'ethereum-cryptography/utils' -import lodash from 'lodash' -import Web3 from 'web3' -import { AccountType, generatePrivateKey } from '../lib/generate_utils' -import { GethRunConfig } from '../lib/interfaces/geth-run-config' -import { ensure0x } from '../lib/utils' -import { getHooks, initAndSyncGethWithRetry, mnemonic, sleep } from './utils' - -const TMP_PATH = '/tmp/e2e' -const validatorUrl = 'http://localhost:8545' -const lightUrl = 'http://localhost:8546' - -const notYetActivatedError = 'support for eth-compatible transactions is not enabled' -const notCompatibleError = 'ethCompatible is true, but non-eth-compatible fields are present' -const noReplayProtectionError = 'only replay-protected (EIP-155) transactions allowed over RPC' - -const validatorPrivateKey = generatePrivateKey(mnemonic, AccountType.VALIDATOR, 0) -const validatorAddress = privateKeyToAddress(validatorPrivateKey) -// Arbitrary addresses to use in the transactions -const toAddress = '0x8c36775E95A5f7FEf6894Ba658628352Ac58605B' -const gatewayFeeRecipientAddress = '0xc77538d1e30C0e4ec44B0DcaD97FD3dc63fcaCC4' - -// Simple contract with a single constant -const bytecode = - '0x608060405260008055348015601357600080fd5b5060358060216000396000f3006080604052600080fd00a165627a7a72305820c7f3f7c299940bb1d9b122d25e8f288817e45bbdeaccdd2f6e8801677ed934e70029' - -const verbose = false - -///////// Configurable values to run only some of the tests during development //////////////// -// ReplayProtectionTests lets you skip or run only the replay-protection tests during dev -// Value when committing should be "run" -// tslint:disable-next-line -let replayProtectionTests: 'run' | 'skip' | 'only' = 'run' -// devFilter can be used during development to only run a subset of testcases. -// But if you're going to commit you should set them all back to undefined (i.e. no filter). -const devFilter: Filter = { - cipIsActivated: undefined, - lightNode: undefined, - ethCompatible: undefined, - contractCreation: undefined, - useFeeCurrency: undefined, - useGatewayFee: undefined, - useGatewayFeeRecipient: undefined, - sendRawTransaction: undefined, -} -/////////////////////////////////////////////////////////////////////////////////////////////// - -// Filter specifies which subset of cases to generate. -// (e.g. {lightNode: true, sendRawTransaction: false} makes it only run cases which send through a light -// node using `eth_sendRawTransaction` -type Filter = Partial - -// TestCase describes the specific case we want to test -interface TestCase { - cipIsActivated: boolean - lightNode: boolean - ethCompatible: boolean - contractCreation: boolean - useFeeCurrency: boolean - useGatewayFee: boolean - useGatewayFeeRecipient: boolean - sendRawTransaction: boolean // whether to use eth_sendRawTransaction ot eth_sendTransaction - errorString: string | null - errorReason: string | null -} - -// generateTestCases is used to generate all the cases we want to test for a setup which -// is either pre-Donut or post-Donut (cipIsActivated true means post-Donut) -function generateTestCases(cipIsActivated: boolean) { - const cases: TestCase[] = [] - if (devFilter.cipIsActivated !== undefined && devFilter.cipIsActivated !== cipIsActivated) { - // The devFilter is incompatible with the cipIsActivated value, so there are no cases to run - return cases - } - const getValues = (fieldFilter: boolean | undefined) => { - return fieldFilter === undefined ? [false, true] : [fieldFilter] - } - // Generate all possible combinations (but some are invalid and excluded using 'continue' below) - for (const lightNode of getValues(devFilter.lightNode)) { - for (const ethCompatible of getValues(devFilter.ethCompatible)) { - for (const contractCreation of getValues(devFilter.contractCreation)) { - for (const useFeeCurrency of getValues(devFilter.useFeeCurrency)) { - for (const useGatewayFee of getValues(devFilter.useGatewayFee)) { - for (const useGatewayFeeRecipient of getValues(devFilter.useGatewayFeeRecipient)) { - for (const sendRawTransaction of getValues(devFilter.sendRawTransaction)) { - let errorString: string | null = null - let errorReason: string | null = null - const hasCeloFields = useFeeCurrency || useGatewayFee || useGatewayFeeRecipient - if (ethCompatible && hasCeloFields) { - errorString = notCompatibleError - errorReason = 'transaction has celo-only fields' - } else if (ethCompatible && !cipIsActivated) { - errorString = notYetActivatedError - errorReason = 'Donut is not activated' - } - if (sendRawTransaction && ethCompatible && hasCeloFields) { - // Such scenarios don't make sense, since eth-compatible transactions in RLP can't have - // these fields. So skip these cases. - continue - } - cases.push({ - cipIsActivated, - lightNode, - ethCompatible, - contractCreation, - useFeeCurrency, - useGatewayFee, - useGatewayFeeRecipient, - sendRawTransaction, - errorString, - errorReason, - }) - } - } - } - } - } - } - } - return cases -} - -function getGethRunConfig(withDonut: boolean, withEspresso: boolean): GethRunConfig { - console.log('getGethRunConfig', withDonut) - return { - migrate: true, - runPath: TMP_PATH, - keepData: false, - networkId: 1101, - network: 'local', - genesisConfig: { - churritoBlock: 0, - donutBlock: withDonut ? 0 : null, - espressoBlock: withEspresso ? 0 : null, - gingerbreadBlock: null, - }, - instances: [ - { - name: 'validator', - validating: true, - syncmode: 'full', - lightserv: true, - port: 30303, - rpcport: 8545, - }, - ], - } -} - -/** - * Copied from ethereumjs-utils - * Trims leading zeros from a `Buffer` or `Number[]`. - * @param a (Buffer|Uint8Array) - * @return (Buffer|Uint8Array) - */ -function stripZeros(a: any): Buffer | Uint8Array { - let first = a[0] - while (a.length > 0 && first.toString() === '0') { - a = a.slice(1) - first = a[0] - } - return a -} - -// TestEnv encapsulates a pre-Donut or post-Donut environment and the tests to run on it -class TestEnv { - testCases: TestCase[] - gethConfig: GethRunConfig - cipIsActivated: boolean - replayProtectionIsNotMandatory: boolean - hooks: ReturnType - stableTokenAddr: string = '' - gasPrice: string = '' - - // There are three cases: (a), (b), and (c) below. - // And, for each of these three cases, we have one which connects to the validator and one which - // connects to the light client. - // (a) contractkit instances without the private key, for transacting using `eth_sendTransaction` - kit: ContractKit - kitLight: ContractKit - // (b) contractkit instances with the private key, for signing locally (to then use `eth_sendRawTransaction`) - kitWithLocalWallet: ContractKit - kitWithLocalWalletLight: ContractKit - // (c) web3 instances with the private key, for generating and signing raw eth-compatible transactions (to then - // use with `eth_sendRawTransaction`) - web3: Web3 - web3Light: Web3 - - constructor(cipIsActivated: boolean, replayProtectionIsNotMandatory: boolean) { - this.gethConfig = getGethRunConfig(cipIsActivated, replayProtectionIsNotMandatory) - this.hooks = getHooks(this.gethConfig) - this.cipIsActivated = cipIsActivated - this.replayProtectionIsNotMandatory = replayProtectionIsNotMandatory - this.testCases = generateTestCases(cipIsActivated) - this.kit = newKitFromWeb3(new Web3(validatorUrl)) - this.kitLight = newKitFromWeb3(new Web3(lightUrl)) - this.kitWithLocalWallet = newKitFromWeb3(new Web3(validatorUrl)) - this.kitWithLocalWalletLight = newKitFromWeb3(new Web3(lightUrl)) - this.web3 = new Web3(validatorUrl) - this.web3Light = new Web3(lightUrl) - } - - // before() does all the setup needed to then enable the individual test cases to be run - async before() { - await this.hooks.before() - - // Restart the validator node and start the light node to connect to it and sync up - await this.hooks.restart() - const lightNodeConfig = { - name: 'light', - validating: false, - syncmode: 'light', - port: 30305, - rpcport: 8546, - } - await initAndSyncGethWithRetry( - this.gethConfig, - this.hooks.gethBinaryPath, - lightNodeConfig, - [...this.gethConfig.instances, lightNodeConfig], - verbose, - 3 - ) - - this.stableTokenAddr = (await this.kit.contracts.getStableToken()).address - const gasPriceMinimum = await (await this.kit.contracts.getGasPriceMinimum()).gasPriceMinimum() - this.gasPrice = gasPriceMinimum.times(5).toString() - - // TODO(mcortesi): magic sleep. without it unlockAccount sometimes fails - await sleep(2) - - // Make sure we can use the validator's address to send transactions - // For signing on the node, unlock the account (and add it first if it's the light node) - await this.kit.connection.web3.eth.personal.unlockAccount(validatorAddress, '', 1000) - await this.kitLight.connection.web3.eth.personal.importRawKey(validatorPrivateKey, '') - await this.kitLight.connection.web3.eth.personal.unlockAccount(validatorAddress, '', 1000) - // For the local wallets, add the private key. - // The web3 instances don't need that, because we use a function that takes in the private key. - this.kitWithLocalWallet.connection.addAccount(validatorPrivateKey) - this.kitWithLocalWalletLight.connection.addAccount(validatorPrivateKey) - } - - async generateUnprotectedTransaction(ethCompatible: boolean): Promise { - const encode = ejsRlp.encode - const numToHex = (x: number | BigNumber) => ejsUtil.bufferToHex(ejsUtil.toBuffer(Number(x))) - const nonce = await this.kit.connection.nonce(validatorAddress) - const celoOnlyFields = ethCompatible ? [] : ['0x', '0x', '0x'] - const arr = [ - nonce > 0 ? numToHex(nonce) : '0x', - numToHex(parseInt(this.gasPrice, 10)), - numToHex(1000000), // plenty of gas - ...celoOnlyFields, - toAddress, // to - '0x05', // value: 5 wei - '0x', // no data - ] - // Creates SHA-3 hash of the RLP encoded version of the input. - const signingHash = ejsUtil.toBuffer(keccak256(ejsRlp.encode(arr))) - const pk = ejsUtil.addHexPrefix(validatorPrivateKey) - const sig = ejsUtil.ecsign(signingHash, ejsUtil.toBuffer(pk)) - arr.push( - ejsUtil.bufferToHex(stripZeros(sig.v) as Buffer), - ejsUtil.bufferToHex(stripZeros(sig.r) as Buffer), - ejsUtil.bufferToHex(stripZeros(sig.s) as Buffer) - ) - return ensure0x(toHex(encode(arr))) - } - - runReplayProtectionTests() { - for (const ethCompatible of [false, true]) { - this.runReplayProtectionTest(ethCompatible) - } - } - - runReplayProtectionTest(ethCompatible: boolean) { - describe(`Transaction without replay protection, ethCompatible: ${ethCompatible}`, () => { - let minedTx: any = null // Use any because we haven't added `ethCompatible` to these types - let error: string | null = null - - before(async () => { - const tx = await this.generateUnprotectedTransaction(ethCompatible) - try { - const receipt = await (await this.kit.connection.sendSignedTransaction(tx)).waitReceipt() - minedTx = await this.kit.web3.eth.getTransaction(receipt.transactionHash) - error = null - } catch (err: any) { - error = err.message - } - }) - if (ethCompatible && !this.cipIsActivated) { - it('fails due to being ethereum-compatible', () => { - assert.isNull(minedTx, 'Transaction succeeded when it should have failed') - assert.equal(error!, notYetActivatedError) - }) - } else if (this.cipIsActivated) { - if (this.replayProtectionIsNotMandatory) { - // Should succeed, since replay protection is optional after Espresso - it('succeeds', () => { - assert.isNull(error, 'Transaction failed when it should have succeeded') - }) - } else { - // Replay protection is mandatory, so the transaction should fail - it('fails due to replay protection being mandatory', () => { - assert.isNull(minedTx, 'Transaction succeeded when it should have failed') - assert.equal(error!, noReplayProtectionError) - }) - } - } else { - // Should succeed, since replay protection is optional before Donut - it('succeeds', () => { - assert.isNull(error, 'Transaction failed when it should have succeeded') - assert.isFalse(minedTx.ethCompatible, 'Transaction has wrong ethCompatible value') - }) - } - }) - } - - runTestCase(testCase: TestCase) { - // Generate a human-readable summary of the test case - const options: string[] = [] - lodash.forEach(testCase, (value, key) => { - if (value === true) { - options.push(key) - } - }) - describe(`Testcase with: ${options.join(', ')}`, () => { - let minedTx: any // Use any because we haven't added `ethCompatible` to these types - let error: string | null = null - - before(async () => { - const tx: CeloTx = { - from: validatorAddress, - gas: 1000000, // plenty for both types of transaction - gasPrice: this.gasPrice, - chainId: this.gethConfig.networkId, - nonce: await this.kit.connection.nonce(validatorAddress), - } - if (testCase.useFeeCurrency) { - tx.feeCurrency = this.stableTokenAddr - } - if (testCase.useGatewayFee) { - tx.gatewayFee = '0x25' - } - if (testCase.useGatewayFeeRecipient) { - tx.gatewayFeeRecipient = gatewayFeeRecipientAddress - } - - if (testCase.contractCreation) { - tx.data = bytecode - } else { - tx.to = await toAddress - tx.value = 5 - } - - try { - let txHash: string - // Use the right contractkit/web3 instances according to whether the testcase say to send - // the transaction through the validator or the light client - const k = testCase.lightNode ? this.kitLight : this.kit - const kLocal = testCase.lightNode ? this.kitWithLocalWalletLight : this.kitWithLocalWallet - const w3 = testCase.lightNode ? this.web3Light : this.web3 - - if (testCase.sendRawTransaction) { - // Sign the transaction locally and send using `eth_sendRawTransaction` - let raw: string - if (testCase.ethCompatible) { - const signed = await w3.eth.accounts.signTransaction(tx, validatorPrivateKey) - raw = signed.rawTransaction! - } else { - const signed = await kLocal.connection.wallet!.signTransaction(tx) - raw = signed.raw - } - // Once the transaction is signed and encoded, it doesn't matter whether we send it with web3 or contractkit - txHash = (await w3.eth.sendSignedTransaction(raw)).transactionHash - } else { - tx.chainId = undefined // clear the chainId b/c web3js won't format it as a hex bignum... - // Send using `eth_sendTransaction` - const params: any = tx // haven't added `ethCompatible` to the tx type - // Only include ethCompatible if it's true. This confirms that omitting it results to normal Celo - // transactions, but doesn't test that ethCompatible: false also does. But we will see in the resulting - // transaction object (from eth_getTransaction) that it has ethCompatible: false. - if (testCase.ethCompatible) { - params.ethCompatible = true - } - const res = await k.sendTransaction(params) - txHash = (await res.waitReceipt()).transactionHash - } - - minedTx = await k.web3.eth.getTransaction(txHash) - error = null - } catch (err: any) { - error = err.message - } - }) - - // Verify that sending the transaction either worked or failed as expected for this test case - if (testCase.errorString !== null) { - it(`fails with the expected error (${testCase.errorReason})`, () => { - assert.notEqual(error, null, "Expected an error but didn't get one") - assert.match( - error!, - new RegExp(testCase.errorString!, 'i'), - `Got "${error}", expected "${testCase.errorString}"` - ) - }) - } else { - it('succeeds', () => { - assert.equal(error, null, 'Got an error but expected the transaction to succeed') - }) - it(`ethCompatible is ${testCase.ethCompatible}`, () => { - assert.equal(minedTx.ethCompatible, testCase.ethCompatible) - }) - } - }) - } -} - -describe('CIP-35 >', function (this: any) { - this.timeout(0) - - describe('before activation', () => { - if (devFilter.cipIsActivated === true) { - return - } - const testEnv = new TestEnv(false, false) // not donut, not espresso - before(async function (this) { - this.timeout(0) - await testEnv.before() - }) - - if (replayProtectionTests !== 'only') { - for (const testCase of testEnv.testCases) { - testEnv.runTestCase(testCase) - } - } - - if (replayProtectionTests !== 'skip') { - testEnv.runReplayProtectionTests() - } - - after(async function (this: any) { - this.timeout(0) - await testEnv.hooks.after() - }) - }) - - describe('after activation', async () => { - if (devFilter.cipIsActivated === false) { - return - } - const testEnv = new TestEnv(true, false) // donut, not espresso - before(async function (this) { - this.timeout(0) - await testEnv.before() - }) - - if (replayProtectionTests !== 'only') { - for (const testCase of testEnv.testCases) { - testEnv.runTestCase(testCase) - } - } - - if (replayProtectionTests !== 'skip') { - testEnv.runReplayProtectionTests() - } - - after(async function (this: any) { - this.timeout(0) - await testEnv.hooks.after() - }) - }) - - describe('after cip50 (optional replay protection)', async () => { - if (devFilter.cipIsActivated === false) { - return - } - const testEnv = new TestEnv(true, true) // donut and espresso - before(async function (this) { - this.timeout(0) - await testEnv.before() - }) - - if (replayProtectionTests !== 'only') { - for (const testCase of testEnv.testCases) { - testEnv.runTestCase(testCase) - } - } - - if (replayProtectionTests !== 'skip') { - testEnv.runReplayProtectionTests() - } - - after(async function (this: any) { - this.timeout(0) - await testEnv.hooks.after() - }) - }) -}) diff --git a/packages/celotool/src/e2e-tests/governance_tests.ts b/packages/celotool/src/e2e-tests/governance_tests.ts deleted file mode 100644 index d89ded096..000000000 --- a/packages/celotool/src/e2e-tests/governance_tests.ts +++ /dev/null @@ -1,1114 +0,0 @@ -// tslint:disable: no-console -import { ContractKit, newKitFromWeb3 } from '@celo/contractkit' -import { getBlsPoP, getBlsPublicKey } from '@celo/cryptographic-utils/lib/bls' -import { eqAddress, privateKeyToAddress } from '@celo/utils/lib/address' -import { concurrentMap } from '@celo/utils/lib/async' -import { fromFixed, toFixed } from '@celo/utils/lib/fixidity' -import { bitIsSet, parseBlockExtraData } from '@celo/utils/lib/istanbul' -import BigNumber from 'bignumber.js' -import { assert } from 'chai' -import Web3 from 'web3' -import { AccountType, generateAddress, generatePrivateKey } from '../lib/generate_utils' -import { connectBipartiteClique, connectPeers, initAndStartGeth } from '../lib/geth' -import { GethInstanceConfig } from '../lib/interfaces/geth-instance-config' -import { GethRunConfig } from '../lib/interfaces/geth-run-config' -import { - assertAlmostEqual, - getHooks, - mnemonic, - sleep, - waitForAnnounceToStabilize, - waitForBlock, - waitForEpochTransition, - waitToFinishInstanceSyncing, -} from './utils' - -interface MemberSwapper { - swap(): Promise -} - -const TMP_PATH = '/tmp/e2e' -const verbose = false -const carbonOffsettingPartnerAddress = '0x1234567812345678123456781234567812345678' -const validatorAddress = '0x47e172f6cfb6c7d01c1574fa3e2be7cc73269d95' -// The tests calculate some expected values based on the rewards multiplier from the block -// before an epoch block. However, the actual rewards multiplier used for epoch rewards is -// calculated inside the epoch block. Since the multiplier depends on the timestamp, this means -// the expected values will never exactly match the actual values, so we need some tolerance. -// This constant defines the tolerance as a fraction of the expected value. -// values. We use 10^-6, so they have to be match to (nearly) 6 significant figures -const tolerance = new BigNumber(10).pow(new BigNumber(-6)) - -async function newMemberSwapper(kit: ContractKit, members: string[]): Promise { - let index = 0 - const group = (await kit.connection.getAccounts())[0] - await Promise.all(members.slice(1).map((member) => removeMember(member))) - - async function removeMember(member: string) { - return (await kit.contracts.getValidators()) - .removeMember(member) - .sendAndWaitForReceipt({ from: group }) - } - - async function addMember(member: string) { - return ( - await (await kit.contracts.getValidators()).addMember(group, member) - ).sendAndWaitForReceipt({ from: group }) - } - - async function getGroupMembers() { - const groupInfo = await (await kit._web3Contracts.getValidators()).methods - .getValidatorGroup(group) - .call() - return groupInfo[0] - } - - return { - async swap() { - const removedMember = members[index % members.length] - await removeMember(members[index % members.length]) - index = index + 1 - const addedMember = members[index % members.length] - await addMember(members[index % members.length]) - const groupMembers = await getGroupMembers() - assert.include(groupMembers, addedMember) - assert.notInclude(groupMembers, removedMember) - }, - } -} - -interface KeyRotator { - rotate(): Promise -} - -async function newKeyRotator( - kit: ContractKit, - kits: ContractKit[], - privateKeys: string[] -): Promise { - let index = 0 - const validator = (await kit.connection.getAccounts())[0] - const accountsWrapper = await kit.contracts.getAccounts() - - async function authorizeValidatorSigner( - signer: string, - signerKit: ContractKit, - signerPrivateKey: string - ) { - const blsPublicKey = getBlsPublicKey(signerPrivateKey) - const blsPop = getBlsPoP(validator, signerPrivateKey) - const accounts = await signerKit.contracts.getAccounts() - const pop = await accounts.generateProofOfKeyPossession(validator, signer) - return ( - await accountsWrapper.authorizeValidatorSignerAndBls(signer, pop, blsPublicKey, blsPop) - ).sendAndWaitForReceipt({ - from: validator, - }) - } - - return { - async rotate() { - if (index < kits.length) { - const signerKit = kits[index] - const signer: string = (await signerKit.connection.getAccounts())[0] - const signerPrivateKey = privateKeys[index] - await authorizeValidatorSigner(signer, signerKit, signerPrivateKey) - index += 1 - assert.equal(await accountsWrapper.getValidatorSigner(validator), signer) - } - }, - } -} - -async function calculateUptime( - kit: ContractKit, - validatorSetSize: number, - lastBlockNumberOfEpoch: number, - epochSize: number, - lookbackWindow: number -): Promise { - const firstBlockNumberOfEpoch = lastBlockNumberOfEpoch - epochSize + 1 - - const monitoringWindow: [number, number] = [ - firstBlockNumberOfEpoch + lookbackWindow - 1, // last block of first lookbackWindow - lastBlockNumberOfEpoch - 2, // we ignore last 2 block fo epoch - ] - const monitoringWindowSize = monitoringWindow[1] - monitoringWindow[0] + 1 - - // we need to obtain monitoring window blocks shifted by 1, since - // we are interested in parentAggregatedSeal that lives on the next block - const blocks = await concurrentMap(10, [...Array(monitoringWindowSize).keys()], (i) => - kit.connection.getBlock(monitoringWindow[0] + 1 + i) - ) - const lastSignedBlock: number[] = new Array(validatorSetSize).fill(0) - const upBlocks: number[] = new Array(validatorSetSize).fill(0) - - // Follows updateUptime() in core/blockchain.go - for (const block of blocks) { - const blockNumber = block.number - 1 // we are actually monitoring prev block signatures - const bitmap = parseBlockExtraData(block.extraData).parentAggregatedSeal.bitmap - - const isMonitoredBlock = - blockNumber >= monitoringWindow[0] && blockNumber <= monitoringWindow[1] - - const currentLookbackWindow: [number, number] = [blockNumber - lookbackWindow + 1, blockNumber] - - for (let signerIndex = 0; signerIndex < validatorSetSize; signerIndex++) { - if (bitIsSet(bitmap, signerIndex)) { - lastSignedBlock[signerIndex] = blockNumber - } - - const lastSignedWithinLookbackwindow = - lastSignedBlock[signerIndex] >= currentLookbackWindow[0] && - lastSignedBlock[signerIndex] <= currentLookbackWindow[1] - - if (isMonitoredBlock && lastSignedWithinLookbackwindow) { - upBlocks[signerIndex]++ - } - } - } - - const maxPotentialUpBlocks = monitoringWindowSize - return upBlocks.map((x) => new BigNumber(x / maxPotentialUpBlocks)) -} - -// TODO(asa): Test independent rotation of ecdsa, bls keys. -describe('governance tests', () => { - const gethConfig: GethRunConfig = { - runPath: TMP_PATH, - verbosity: 3, - migrate: true, - networkId: 1101, - network: 'local', - genesisConfig: { - churritoBlock: 0, - donutBlock: 0, - espressoBlock: 0, - epoch: 10, - }, - instances: [ - // Validators 0 and 1 are swapped in and out of the group. - { - name: 'validator0', - validating: true, - syncmode: 'full', - port: 30303, - rpcport: 8545, - }, - { - name: 'validator1', - validating: true, - syncmode: 'full', - port: 30305, - rpcport: 8547, - }, - // Validator 2 will authorize a validating key every other epoch. - { - name: 'validator2', - validating: true, - syncmode: 'full', - port: 30307, - rpcport: 8549, - }, - { - name: 'validator3', - validating: true, - syncmode: 'full', - port: 30309, - rpcport: 8551, - }, - { - name: 'validator4', - validating: true, - syncmode: 'full', - port: 30311, - rpcport: 8553, - }, - ], - } - - const hooks: any = getHooks(gethConfig) - - let web3: Web3 - let election: any - let stableToken: any - let sortedOracles: any - let epochRewards: any - let goldToken: any - let reserve: any - let validators: any - let accounts: any - let kit: ContractKit - - before(async function (this: any) { - this.timeout(0) - // Comment out the following line after a local run for a quick rerun. - await hooks.before() - }) - - after(async function (this: any) { - this.timeout(0) - await hooks.after() - }) - - const restart = async () => { - await hooks.restart() - web3 = new Web3('http://localhost:8545') - kit = newKitFromWeb3(web3) - // TODO(mcortesi): magic sleep. without it unlockAccount sometimes fails - await sleep(2) - // Assuming empty password - await kit.connection.web3.eth.personal.unlockAccount(validatorAddress, '', 1000000) - - goldToken = await kit._web3Contracts.getGoldToken() - stableToken = await kit._web3Contracts.getStableToken() - sortedOracles = await kit._web3Contracts.getSortedOracles() - validators = await kit._web3Contracts.getValidators() - reserve = await kit._web3Contracts.getReserve() - election = await kit._web3Contracts.getElection() - epochRewards = await kit._web3Contracts.getEpochRewards() - accounts = await kit._web3Contracts.getAccounts() - - await waitForBlock(web3, 1) - await waitForAnnounceToStabilize(web3) - - const er = await kit._web3Contracts.getEpochRewards() - const fraction = await er.methods.getCarbonOffsettingFraction().call() - await er.methods - .setCarbonOffsettingFund(carbonOffsettingPartnerAddress, fraction) - .send({ from: validatorAddress }) - } - - const getValidatorGroupMembers = async (blockNumber?: number) => { - if (blockNumber) { - const [groupAddress] = await validators.methods - .getRegisteredValidatorGroups() - .call({}, blockNumber) - const groupInfo = await validators.methods - .getValidatorGroup(groupAddress) - .call({}, blockNumber) - return groupInfo[0] - } else { - const [groupAddress] = await validators.methods.getRegisteredValidatorGroups().call() - const groupInfo = await validators.methods.getValidatorGroup(groupAddress).call() - return groupInfo[0] - } - } - - const getValidatorSigner = async (address: string, blockNumber?: number) => { - if (blockNumber) { - return accounts.methods.getValidatorSigner(address).call({}, blockNumber) - } else { - return accounts.methods.getValidatorSigner(address).call() - } - } - - const getValidatorGroupPrivateKey = async () => { - const [groupAddress] = await validators.methods.getRegisteredValidatorGroups().call() - // If we're using mycelo, we can just generate the validator group key directly - const myceloAddress = generateAddress(mnemonic, AccountType.VALIDATOR_GROUP, 0) - if (myceloAddress === groupAddress) { - return '0x' + generatePrivateKey(mnemonic, AccountType.VALIDATOR_GROUP, 0) - } - // Otherwise, the validator group key is encoded in its name (see 25_elect_validators.ts) - const name = await accounts.methods.getName(groupAddress).call() - const encryptedKeystore64 = name.split(' ')[1] - const encryptedKeystore = JSON.parse(Buffer.from(encryptedKeystore64, 'base64').toString()) - // The validator group ID is the validator group keystore encrypted with validator 0's - // private key. - const encryptionKey = `0x${gethConfig.instances[0].privateKey}` - const decryptedKeystore = web3.eth.accounts.decrypt(encryptedKeystore, encryptionKey) - return decryptedKeystore.privateKey - } - - const isLastBlockOfEpoch = (blockNumber: number, epochSize: number) => - blockNumber % epochSize === 0 - - const assertBalanceChanged = async ( - address: string, - blockNumber: number, - expected: BigNumber, - token: any - ) => { - const currentBalance = new BigNumber( - await token.methods.balanceOf(address).call({}, blockNumber) - ) - const previousBalance = new BigNumber( - await token.methods.balanceOf(address).call({}, blockNumber - 1) - ) - assert.isFalse(currentBalance.isNaN()) - assert.isFalse(previousBalance.isNaN()) - const margin = expected.times(tolerance) - assertAlmostEqual(currentBalance.minus(previousBalance), expected, margin) - } - - const assertTargetVotingYieldChanged = async (blockNumber: number, expected: BigNumber) => { - const currentTarget = new BigNumber( - (await epochRewards.methods.getTargetVotingYieldParameters().call({}, blockNumber))[0] - ) - const previousTarget = new BigNumber( - (await epochRewards.methods.getTargetVotingYieldParameters().call({}, blockNumber - 1))[0] - ) - const max = new BigNumber( - (await epochRewards.methods.getTargetVotingYieldParameters().call({}, blockNumber))[1] - ) - const expectedTarget = previousTarget.plus(expected) - if (expectedTarget.isGreaterThanOrEqualTo(max)) { - assert.equal(currentTarget.toFixed(), max.toFixed()) - } else if (expectedTarget.isLessThanOrEqualTo(0)) { - assert.isTrue(currentTarget.isZero()) - } else { - const difference = currentTarget.minus(previousTarget) - // Assert equal to 9 decimal places due to rounding errors. - assert.equal(fromFixed(difference).dp(9).toFixed(), fromFixed(expected).dp(9).toFixed()) - } - } - - const assertTargetVotingYieldUnchanged = (blockNumber: number) => - assertTargetVotingYieldChanged(blockNumber, new BigNumber(0)) - - const getLastEpochBlock = (blockNumber: number, epoch: number) => { - const epochNumber = Math.floor((blockNumber - 1) / epoch) - return epochNumber * epoch - } - - const assertGoldTokenTotalSupplyUnchanged = (blockNumber: number) => - assertGoldTokenTotalSupplyChanged(blockNumber, new BigNumber(0)) - - const assertGoldTokenTotalSupplyChanged = async (blockNumber: number, expected: BigNumber) => { - const currentSupply = new BigNumber(await goldToken.methods.totalSupply().call({}, blockNumber)) - const previousSupply = new BigNumber( - await goldToken.methods.totalSupply().call({}, blockNumber - 1) - ) - assertAlmostEqual(currentSupply.minus(previousSupply), expected) - } - - describe('when the validator set is changing', () => { - const blockNumbers: number[] = [] - - let epoch: number - let validatorAccounts: string[] - - before(async function (this: any) { - this.timeout(0) // Disable test timeout - - await restart() - - const groupPrivateKey = await getValidatorGroupPrivateKey() - - const validatorGroup: GethInstanceConfig = { - name: 'validatorGroup', - validating: false, - syncmode: 'full', - port: 30313, - wsport: 8555, - rpcport: 8557, - privateKey: groupPrivateKey.slice(2), - } - - await initAndStartGeth(gethConfig, hooks.gethBinaryPath, validatorGroup, verbose) - - await connectPeers([...gethConfig.instances, validatorGroup], verbose) - - await waitToFinishInstanceSyncing(validatorGroup) - - validatorAccounts = await getValidatorGroupMembers() - assert.equal(validatorAccounts.length, 5) - epoch = new BigNumber(await validators.methods.getEpochSize().call()).toNumber() - assert.equal(epoch, 10) - - // Wait for an epoch transition so we can activate our vote. - await waitForEpochTransition(web3, epoch) - await sleep(5.5) - // Wait for an extra epoch transition to ensure everyone is connected to one another. - await waitForEpochTransition(web3, epoch) - - const groupWeb3Url = 'ws://localhost:8555' - - // Prepare for member swapping. - const groupWeb3 = new Web3(groupWeb3Url) - - const groupKit = newKitFromWeb3(groupWeb3) - - const group: string = (await groupWeb3.eth.getAccounts())[0] - // Send some funds to the group, so it can afford fees - await ( - await kit.sendTransaction({ - from: validatorAddress, - to: group, - value: Web3.utils.toWei('1', 'ether'), - }) - ).waitReceipt() - - // groupKit uses a different node than kit does, so wait a second in case kit's node - // got the new block before groupKit's node did. - await sleep(1) - const txos = await (await groupKit.contracts.getElection()).activate(group) - for (const txo of txos) { - await txo.sendAndWaitForReceipt({ from: group }) - } - - validators = await groupKit._web3Contracts.getValidators() - const membersToSwap = [validatorAccounts[0], validatorAccounts[1]] - const memberSwapper = await newMemberSwapper(groupKit, membersToSwap) - // The memberSwapper makes a change when it's created, so we wait for epoch change so it takes effect - await waitForEpochTransition(web3, epoch) - - const handled: any = {} - - let errorWhileChangingValidatorSet = '' - const changeValidatorSet = async (header: any) => { - try { - if (handled[header.number]) { - return - } - handled[header.number] = true - blockNumbers.push(header.number) - // At the start of epoch N, perform actions so the validator set is different for epoch N + 1. - // Note that all of these actions MUST complete within the epoch. - if (header.number % epoch === 0 && errorWhileChangingValidatorSet === '') { - // 1. Swap validator0 and validator1 so one is a member of the group and the other is not. - // 2. Rotate keys for validator 2 by authorizing a new validating key. - await memberSwapper.swap() - } - } catch (e: any) { - console.error(e) - errorWhileChangingValidatorSet = e.toString() - } - } - - const subscription = groupWeb3.eth.subscribe('newBlockHeaders') - subscription.on('data', changeValidatorSet) - - // Wait for a few epochs while changing the validator set. - while (blockNumbers.length < 40) { - // Prepare for member swapping. - await sleep(epoch) - } - ;(subscription as any).unsubscribe() - - // Wait for the current epoch to complete. - await sleep(epoch) - assert.equal(errorWhileChangingValidatorSet, '') - }) - - const getValidatorSetSignersAtBlock = async (blockNumber: number): Promise => { - return election.methods.getCurrentValidatorSigners().call({}, blockNumber) - } - - const getValidatorSetAccountsAtBlock = async (blockNumber: number) => { - const signingKeys = await getValidatorSetSignersAtBlock(blockNumber) - return Promise.all( - signingKeys.map((address: string) => - accounts.methods.signerToAccount(address).call({}, blockNumber) - ) - ) - } - - it('should always return a validator set size equal to the number of group members at the end of the last epoch', async () => { - for (const blockNumber of blockNumbers) { - const lastEpochBlock = getLastEpochBlock(blockNumber, epoch) - const validatorSetSize = await election.methods - .numberValidatorsInCurrentSet() - .call({}, blockNumber) - const groupMembership = await getValidatorGroupMembers(lastEpochBlock) - assert.equal(validatorSetSize, groupMembership.length) - } - }) - - it('should always return a validator set equal to the signing keys of the group members at the end of the last epoch', async function (this: any) { - this.timeout(0) - for (const blockNumber of blockNumbers) { - const lastEpochBlock = getLastEpochBlock(blockNumber, epoch) - const memberAccounts = await getValidatorGroupMembers(lastEpochBlock) - const memberSigners = await Promise.all( - memberAccounts.map((v: string) => getValidatorSigner(v, lastEpochBlock)) - ) - const validatorSetSigners = await getValidatorSetSignersAtBlock(blockNumber) - const validatorSetAccounts = await getValidatorSetAccountsAtBlock(blockNumber) - assert.sameMembers(memberSigners, validatorSetSigners) - assert.sameMembers(memberAccounts, validatorSetAccounts) - } - }) - - it('should block propose in a round robin fashion', async () => { - let roundRobinOrder: string[] = [] - for (const blockNumber of blockNumbers) { - const lastEpochBlock = getLastEpochBlock(blockNumber, epoch) - // Fetch the round robin order if it hasn't already been set for this epoch. - if (roundRobinOrder.length === 0 || blockNumber === lastEpochBlock + 1) { - const validatorSet = await getValidatorSetSignersAtBlock(blockNumber) - roundRobinOrder = await Promise.all( - validatorSet.map( - async (_, i) => (await web3.eth.getBlock(lastEpochBlock + i + 1)).miner - ) - ) - assert.sameMembers(roundRobinOrder, validatorSet) - } - const indexInEpoch = blockNumber - lastEpochBlock - 1 - const expectedProposer = roundRobinOrder[indexInEpoch % roundRobinOrder.length] - const block = await web3.eth.getBlock(blockNumber) - assert(eqAddress(block.miner, expectedProposer)) - } - }) - - it('should update the validator scores at the end of each epoch', async function (this: any) { - this.timeout(0) - const scoreParams = await validators.methods.getValidatorScoreParameters().call() - const exponent = new BigNumber(scoreParams[0]) - const adjustmentSpeed = fromFixed(new BigNumber(scoreParams[1])) - - const assertScoreUnchanged = async (validator: string, blockNumber: number) => { - const score = new BigNumber( - (await validators.methods.getValidator(validator).call({}, blockNumber)).score - ) - const previousScore = new BigNumber( - (await validators.methods.getValidator(validator).call({}, blockNumber - 1)).score - ) - assert.isFalse(score.isNaN()) - assert.isFalse(previousScore.isNaN()) - assert.equal(score.toFixed(), previousScore.toFixed()) - } - - const assertScoreChanged = async ( - validator: string, - blockNumber: number, - uptime: BigNumber - ) => { - const score = new BigNumber( - (await validators.methods.getValidator(validator).call({}, blockNumber)).score - ) - const previousScore = new BigNumber( - (await validators.methods.getValidator(validator).call({}, blockNumber - 1)).score - ) - assert.isFalse(score.isNaN()) - assert.isFalse(previousScore.isNaN()) - - const epochScore = uptime.exponentiatedBy(exponent) - const expectedScore = BigNumber.minimum( - epochScore, - adjustmentSpeed - .times(epochScore) - .plus(new BigNumber(1).minus(adjustmentSpeed).times(fromFixed(previousScore))) - ) - assertAlmostEqual(score, toFixed(expectedScore)) - } - - for (const blockNumber of blockNumbers) { - let expectUnchangedScores: string[] - let expectChangedScores: string[] - let electedValidators: string[] - let uptime: BigNumber[] - if (isLastBlockOfEpoch(blockNumber, epoch)) { - expectChangedScores = await getValidatorSetAccountsAtBlock(blockNumber) - expectUnchangedScores = validatorAccounts.filter((x) => !expectChangedScores.includes(x)) - electedValidators = await getValidatorSetAccountsAtBlock(blockNumber) - uptime = await calculateUptime(kit, electedValidators.length, blockNumber, epoch, 3) - } else { - expectUnchangedScores = validatorAccounts - expectChangedScores = [] - electedValidators = [] - uptime = [] - } - - for (const validator of expectUnchangedScores) { - await assertScoreUnchanged(validator, blockNumber) - } - - for (const validator of expectChangedScores) { - const signerIndex = electedValidators.map(eqAddress.bind(null, validator)).indexOf(true) - await assertScoreChanged(validator, blockNumber, uptime[signerIndex]) - } - } - }) - - it('should distribute epoch payments at the end of each epoch', async function (this: any) { - this.timeout(0) - const commission = 0.1 - const targetValidatorEpochPayment = new BigNumber( - await epochRewards.methods.targetValidatorEpochPayment().call() - ) - const [group] = await validators.methods.getRegisteredValidatorGroups().call() - - const assertBalanceUnchanged = async (validator: string, blockNumber: number) => { - await assertBalanceChanged(validator, blockNumber, new BigNumber(0), stableToken) - } - - const getExpectedTotalPayment = async (validator: string, blockNumber: number) => { - const score = new BigNumber( - (await validators.methods.getValidator(validator).call({}, blockNumber)).score - ) - assert.isFalse(score.isNaN()) - // We need to calculate the rewards multiplier for the previous block, before - // the rewards actually are awarded. - const rewardsMultiplier = new BigNumber( - await epochRewards.methods.getRewardsMultiplier().call({}, blockNumber - 1) - ) - return targetValidatorEpochPayment - .times(fromFixed(score)) - .times(fromFixed(rewardsMultiplier)) - } - - for (const blockNumber of blockNumbers) { - let expectUnchangedBalances: string[] - let expectChangedBalances: string[] - if (isLastBlockOfEpoch(blockNumber, epoch)) { - expectChangedBalances = await getValidatorSetAccountsAtBlock(blockNumber) - expectUnchangedBalances = validatorAccounts.filter( - (x) => !expectChangedBalances.includes(x) - ) - } else { - expectUnchangedBalances = validatorAccounts - expectChangedBalances = [] - } - - for (const validator of expectUnchangedBalances) { - await assertBalanceUnchanged(validator, blockNumber) - } - - let expectedGroupPayment = new BigNumber(0) - for (const validator of expectChangedBalances) { - const expectedTotalPayment = await getExpectedTotalPayment(validator, blockNumber) - const groupPayment = expectedTotalPayment.times(commission) - await assertBalanceChanged( - validator, - blockNumber, - expectedTotalPayment.minus(groupPayment), - stableToken - ) - expectedGroupPayment = expectedGroupPayment.plus(groupPayment) - } - await assertBalanceChanged(group, blockNumber, expectedGroupPayment, stableToken) - } - }) - - it('should distribute epoch rewards at the end of each epoch', async function (this: any) { - this.timeout(0) - const lockedGold = await kit._web3Contracts.getLockedGold() - const governance = await kit._web3Contracts.getGovernance() - const gasPriceMinimum = await kit._web3Contracts.getGasPriceMinimum() - const [group] = await validators.methods.getRegisteredValidatorGroups().call() - - const assertVotesChanged = async (blockNumber: number, expected: BigNumber) => { - const currentVotes = new BigNumber( - await election.methods.getTotalVotesForGroup(group).call({}, blockNumber) - ) - const previousVotes = new BigNumber( - await election.methods.getTotalVotesForGroup(group).call({}, blockNumber - 1) - ) - const margin = expected.times(tolerance) - assertAlmostEqual(currentVotes.minus(previousVotes), expected, margin) - } - - // Returns the gas fee base for a given block, which is distributed to the governance contract. - const blockBaseGasFee = async (blockNumber: number): Promise => { - const gas = (await web3.eth.getBlock(blockNumber)).gasUsed - // @ts-ignore - TODO: remove when web3 upgrade completed - const gpm = await gasPriceMinimum.methods.gasPriceMinimum().call({}, blockNumber) - return new BigNumber(gpm).times(new BigNumber(gas)) - } - - const assertLockedGoldBalanceChanged = async (blockNumber: number, expected: BigNumber) => { - await assertBalanceChanged(lockedGold.options.address, blockNumber, expected, goldToken) - } - - const assertGovernanceBalanceChanged = async (blockNumber: number, expected: BigNumber) => { - await assertBalanceChanged(governance.options.address, blockNumber, expected, goldToken) - } - - const assertReserveBalanceChanged = async (blockNumber: number, expected: BigNumber) => { - await assertBalanceChanged(reserve.options.address, blockNumber, expected, goldToken) - } - - const assertCarbonOffsettingBalanceChanged = async ( - blockNumber: number, - expected: BigNumber - ) => { - await assertBalanceChanged(carbonOffsettingPartnerAddress, blockNumber, expected, goldToken) - } - - const assertVotesUnchanged = async (blockNumber: number) => { - await assertVotesChanged(blockNumber, new BigNumber(0)) - } - - const assertLockedGoldBalanceUnchanged = async (blockNumber: number) => { - await assertLockedGoldBalanceChanged(blockNumber, new BigNumber(0)) - } - - const assertReserveBalanceUnchanged = async (blockNumber: number) => { - await assertReserveBalanceChanged(blockNumber, new BigNumber(0)) - } - - const assertCarbonOffsettingBalanceUnchanged = async (blockNumber: number) => { - await assertCarbonOffsettingBalanceChanged(blockNumber, new BigNumber(0)) - } - - const getStableTokenSupplyChange = async (blockNumber: number) => { - const currentSupply = new BigNumber( - await stableToken.methods.totalSupply().call({}, blockNumber) - ) - const previousSupply = new BigNumber( - await stableToken.methods.totalSupply().call({}, blockNumber - 1) - ) - return currentSupply.minus(previousSupply) - } - - const getStableTokenExchangeRate = async (blockNumber: number) => { - const rate = await sortedOracles.methods - .medianRate(stableToken.options.address) - .call({}, blockNumber) - return new BigNumber(rate[0]).div(rate[1]) - } - - for (const blockNumber of blockNumbers) { - if (isLastBlockOfEpoch(blockNumber, epoch)) { - // We use the number of active votes from the previous block to calculate the expected - // epoch reward as the number of active votes for the current block will include the - // epoch reward. - const activeVotes = new BigNumber( - await election.methods.getActiveVotes().call({}, blockNumber - 1) - ) - assert.isFalse(activeVotes.isZero()) - - // We need to calculate the rewards multiplier for the previous block, before - // the rewards actually are awarded. - const rewardsMultiplier = new BigNumber( - await epochRewards.methods.getRewardsMultiplier().call({}, blockNumber - 1) - ) - assert.isFalse(rewardsMultiplier.isZero()) - - // This is the array of rewards that should have been distributed - const targetRewards = await epochRewards.methods - .calculateTargetEpochRewards() - .call({}, blockNumber - 1) - // This is with reward multiplier - const perValidatorReward = new BigNumber(targetRewards[0]) - const validatorSetSize = await election.methods - .numberValidatorsInCurrentSet() - .call({}, blockNumber - 1) - const exchangeRate = await getStableTokenExchangeRate(blockNumber) - // Calculate total validator reward in gold to calc infra reward - const maxPotentialValidatorReward = perValidatorReward - .times(validatorSetSize) - .div(exchangeRate) - // Calculate the expected voting reward - const targetVotingYield = new BigNumber( - (await epochRewards.methods.getTargetVotingYieldParameters().call({}, blockNumber))[0] - ) - assert.isFalse(targetVotingYield.isZero()) - const expectedVoterRewards = activeVotes - .times(fromFixed(targetVotingYield)) - .times(fromFixed(rewardsMultiplier)) - - // infra: (x / (1 - x)) * predicted supply increase * rewards mult - const communityRewardFrac = new BigNumber( - await epochRewards.methods.getCommunityRewardFraction().call({}, blockNumber) - ) - const carbonOffsettingFrac = new BigNumber( - await epochRewards.methods.getCarbonOffsettingFraction().call({}, blockNumber) - ) - - const fundFactor = new BigNumber(1) - .minus(fromFixed(communityRewardFrac)) - .minus(fromFixed(carbonOffsettingFrac)) - - const expectedCommunityReward = expectedVoterRewards - .plus(maxPotentialValidatorReward) - .times(fromFixed(communityRewardFrac)) - .div(fundFactor) - - const expectedCarbonOffsettingPartnerAward = expectedVoterRewards - .plus(maxPotentialValidatorReward) - .times(fromFixed(carbonOffsettingFrac)) - .div(fundFactor) - - const stableTokenSupplyChange = await getStableTokenSupplyChange(blockNumber) - const expectedGoldTotalSupplyChange = expectedCommunityReward - .plus(expectedVoterRewards) - .plus(expectedCarbonOffsettingPartnerAward) - .plus(stableTokenSupplyChange.div(exchangeRate)) - // Check TS calc'd rewards against solidity calc'd rewards - const totalVoterRewards = new BigNumber(targetRewards[1]) - const totalCommunityReward = new BigNumber(targetRewards[2]) - const carbonOffsettingPartnerAward = new BigNumber(targetRewards[3]) - assertAlmostEqual(expectedVoterRewards, totalVoterRewards) - assertAlmostEqual(expectedCommunityReward, totalCommunityReward) - assertAlmostEqual(expectedCarbonOffsettingPartnerAward, carbonOffsettingPartnerAward) - // Check TS calc'd rewards against what happened - await assertVotesChanged(blockNumber, expectedVoterRewards) - await assertLockedGoldBalanceChanged(blockNumber, expectedVoterRewards) - await assertGovernanceBalanceChanged( - blockNumber, - expectedCommunityReward.plus(await blockBaseGasFee(blockNumber)) - ) - await assertReserveBalanceChanged(blockNumber, stableTokenSupplyChange.div(exchangeRate)) - await assertGoldTokenTotalSupplyChanged(blockNumber, expectedGoldTotalSupplyChange) - await assertCarbonOffsettingBalanceChanged( - blockNumber, - expectedCarbonOffsettingPartnerAward - ) - } else { - await assertVotesUnchanged(blockNumber) - await assertGoldTokenTotalSupplyUnchanged(blockNumber) - await assertLockedGoldBalanceUnchanged(blockNumber) - await assertReserveBalanceUnchanged(blockNumber) - await assertGovernanceBalanceChanged(blockNumber, await blockBaseGasFee(blockNumber)) - await assertCarbonOffsettingBalanceUnchanged(blockNumber) - } - } - }) - - it('should update the target voting yield', async () => { - for (const blockNumber of blockNumbers) { - if (isLastBlockOfEpoch(blockNumber, epoch)) { - // We use the voting gold fraction from before the rewards are granted. - const votingGoldFraction = new BigNumber( - await epochRewards.methods.getVotingGoldFraction().call({}, blockNumber - 1) - ) - const targetVotingGoldFraction = new BigNumber( - await epochRewards.methods.getTargetVotingGoldFraction().call({}, blockNumber) - ) - const difference = targetVotingGoldFraction.minus(votingGoldFraction) - const adjustmentFactor = fromFixed( - new BigNumber( - (await epochRewards.methods.getTargetVotingYieldParameters().call({}, blockNumber))[2] - ) - ) - const delta = difference.times(adjustmentFactor) - await assertTargetVotingYieldChanged(blockNumber, delta) - } else { - await assertTargetVotingYieldUnchanged(blockNumber) - } - } - }) - - it('should have emitted the correct events when paying epoch rewards', async () => { - const currentBlock = (await web3.eth.getBlock('latest')).number - const events = [ - { - contract: epochRewards, - name: 'TargetVotingYieldUpdated', - }, - { - contract: validators, - name: 'ValidatorEpochPaymentDistributed', - }, - { - contract: validators, - name: 'ValidatorScoreUpdated', - }, - { - contract: election, - name: 'EpochRewardsDistributedToVoters', - }, - ] - for (const event of events) { - const eventLogs = await event.contract.getPastEvents(event.name, { - fromBlock: currentBlock - 10, - currentBlock, - }) - assert( - eventLogs.every((a: any) => a.blockNumber % 10 === 0), - `every ${event.name} event occured on the last block of the epoch` - ) - assert(eventLogs.length > 0, `at least one ${event.name} event occured`) - } - }) - }) - - describe('when rotating keys', () => { - const blockNumbers: number[] = [] - const miners: string[] = [] - const rotation0PrivateKey = '0xa42ac9c99f6ab2c96ee6cae1b40d36187f65cd878737f6623cd363fb94ba7087' - const rotation1PrivateKey = '0x4519cae145fb9499358be484ca60c80d8f5b7f9c13ff82c88ec9e13283e9de1a' - - const rotation0Address = privateKeyToAddress(rotation0PrivateKey) - const rotation1Address = privateKeyToAddress(rotation1PrivateKey) - - let epoch: number - let validatorAccounts: string[] - - before(async function (this: any) { - this.timeout(0) // Disable test timeout - - await restart() - - const groupPrivateKey = await getValidatorGroupPrivateKey() - - const validatorGroup: GethInstanceConfig = { - name: 'validatorGroup', - validating: false, - syncmode: 'full', - port: 30313, - wsport: 8555, - rpcport: 8557, - privateKey: groupPrivateKey.slice(2), - } - - await initAndStartGeth(gethConfig, hooks.gethBinaryPath, validatorGroup, verbose) - - await connectPeers([...gethConfig.instances, validatorGroup], verbose) - - console.log('wait for validatorGroup to finish syncing') - await waitToFinishInstanceSyncing(validatorGroup) - - const additionalValidatingNodes: GethInstanceConfig[] = [ - { - name: 'validator2KeyRotation0', - validating: true, - syncmode: 'full', - lightserv: false, - port: 30315, - wsport: 8559, - rpcport: 9559, - privateKey: rotation0PrivateKey.slice(2), - minerValidator: privateKeyToAddress(rotation0PrivateKey.slice(2)), - }, - { - name: 'validator2KeyRotation1', - validating: true, - syncmode: 'full', - lightserv: false, - port: 30317, - wsport: 8561, - rpcport: 9561, - privateKey: rotation1PrivateKey.slice(2), - minerValidator: privateKeyToAddress(rotation1PrivateKey.slice(2)), - }, - ] - - await Promise.all( - additionalValidatingNodes.map((nodeConfig: GethInstanceConfig) => - initAndStartGeth(gethConfig, hooks.gethBinaryPath, nodeConfig, verbose) - ) - ) - - // Connect the validating nodes to the non-validating nodes, to test that announce messages are properly gossiped. - await connectBipartiteClique(gethConfig.instances, additionalValidatingNodes, verbose) - - console.log('wait for new validators to sync') - await Promise.all(additionalValidatingNodes.map((i) => waitToFinishInstanceSyncing(i))) - - validatorAccounts = await getValidatorGroupMembers() - assert.equal(validatorAccounts.length, 5) - epoch = new BigNumber(await validators.methods.getEpochSize().call()).toNumber() - assert.equal(epoch, 10) - - console.log('wait for end of epoch') - // Wait for an epoch transition to ensure everyone is connected to one another. - await waitForEpochTransition(web3, epoch) - - const groupWeb3Url = 'ws://localhost:8555' - const groupWeb3 = new Web3(groupWeb3Url) - - const groupKit = newKitFromWeb3(groupWeb3) - - // Prepare for key rotation. - const validatorRpc = 'http://localhost:8549' - const validatorWeb3 = new Web3(validatorRpc) - const authWeb31 = 'ws://localhost:8559' - const authWeb32 = 'ws://localhost:8561' - const authorizedKits = [ - newKitFromWeb3(new Web3(authWeb31)), - newKitFromWeb3(new Web3(authWeb32)), - ] - const authorizedPrivateKeys = [rotation0PrivateKey, rotation1PrivateKey] - const keyRotator = await newKeyRotator( - newKitFromWeb3(validatorWeb3), - authorizedKits, - authorizedPrivateKeys - ) - - const handled: any = {} - - let errorWhileChangingValidatorSet = '' - let lastRotated = 0 - const changeValidatorSet = async (header: any) => { - try { - if (handled[header.number]) { - return - } - handled[header.number] = true - blockNumbers.push(header.number) - miners.push(header.miner) - // At the start of epoch N, perform actions so the validator set is different for epoch N + 1. - // Note that all of these actions MUST complete within the epoch. - if ( - header.number % 10 === 0 && - errorWhileChangingValidatorSet === '' && - lastRotated + 60 <= header.number - ) { - // 1. Swap validator0 and validator1 so one is a member of the group and the other is not. - // 2. Rotate keys for validator 2 by authorizing a new validating key. - lastRotated = header.number - await keyRotator.rotate() - } - } catch (e: any) { - console.error(e) - errorWhileChangingValidatorSet = e.toString() - } - } - - const subscription = groupKit.connection.web3.eth.subscribe('newBlockHeaders') - subscription.on('data', changeValidatorSet) - - // Wait for a few epochs while changing the validator set. - while (blockNumbers.length < 180) { - // Prepare for member swapping. - await sleep(epoch) - } - ;(subscription as any).unsubscribe() - - // Wait for the current epoch to complete. - await sleep(epoch) - assert.equal(errorWhileChangingValidatorSet, '') - }) - - it('validator 0 should have signed at least one block', async () => { - const rotation0MinedBlock = miners.some((a) => eqAddress(a, rotation0Address)) - if (!rotation0MinedBlock) { - console.log(rotation0Address, rotation1Address, miners) - } - assert.isTrue(rotation0MinedBlock) - }) - - it('validator 1 should have signed at least one block', async () => { - const rotation1MinedBlock = miners.some((a) => eqAddress(a, rotation1Address)) - if (!rotation1MinedBlock) { - console.log(rotation0Address, rotation1Address, miners) - } - assert.isTrue(rotation1MinedBlock) - }) - }) - - describe('when rewards distribution is frozen', () => { - let epoch: number - let blockFrozen: number - let latestBlock: number - - before(async function (this: any) { - this.timeout(0) - await restart() - const validator = (await kit.connection.getAccounts())[0] - await kit.connection.web3.eth.personal.unlockAccount(validator, '', 1000000) - const freezer = await kit._web3Contracts.getFreezer() - await freezer.methods.freeze(epochRewards.options.address).send({ from: validator }) - blockFrozen = await kit.connection.getBlockNumber() - epoch = new BigNumber(await validators.methods.getEpochSize().call()).toNumber() - await waitForBlock(kit.connection.web3, blockFrozen + epoch * 2) - latestBlock = await kit.connection.getBlockNumber() - }) - - it('should not update the target voing yield', async () => { - for (let blockNumber = blockFrozen; blockNumber < latestBlock; blockNumber++) { - await assertTargetVotingYieldUnchanged(blockNumber) - } - }) - - it('should not mint new Celo Gold', async () => { - for (let blockNumber = blockFrozen; blockNumber < latestBlock; blockNumber++) { - await assertGoldTokenTotalSupplyUnchanged(blockNumber) - } - }) - }) -}) diff --git a/packages/celotool/src/e2e-tests/replica_tests.ts b/packages/celotool/src/e2e-tests/replica_tests.ts deleted file mode 100644 index c29a2f3ee..000000000 --- a/packages/celotool/src/e2e-tests/replica_tests.ts +++ /dev/null @@ -1,264 +0,0 @@ -import { BlockHeader } from '@celo/connect' -import { HttpRpcCaller, RpcCaller } from '@celo/connect/lib/utils/rpc-caller' -import { privateKeyToAddress } from '@celo/utils/lib/address' -import { bitIsSet, parseBlockExtraData } from '@celo/utils/lib/istanbul' -import { assert } from 'chai' -import Web3 from 'web3' -import { privateKeyToPublicKey } from '../lib/generate_utils' -import { getEnodeAddress, initAndStartGeth } from '../lib/geth' -import { GethInstanceConfig } from '../lib/interfaces/geth-instance-config' -import { GethRunConfig } from '../lib/interfaces/geth-run-config' -import { getHooks, sleep, waitForEpochTransition, waitToFinishInstanceSyncing } from './utils' - -enum IstanbulManagement { - getSnapshot = 'istanbul_getSnapshot', - getValidators = 'istanbul_getValidators', - getValidatorsBLSPublicKeys = 'istanbul_getValidatorsBLSPublicKeys', - getProposer = 'istanbul_getProposer', - addProxy = 'istanbul_addProxy', - removeProxy = 'istanbul_removeProxy', - startAtBlock = 'istanbul_startValidatingAtBlock', - stopAtBlock = 'istanbul_stopValidatingAtBlock', - startValidating = 'istanbul_startValidating', - stopValidating = 'istanbul_stopValidating', - valEnodeTableInfo = 'istanbul_getValEnodeTable', - versionCertificateTableInfo = 'istanbul_getVersionCertificateTableInfo', - currentRoundState = 'istanbul_getCurrentRoundState', - proxies = 'istanbul_getProxiesInfo', - proxiedValidators = 'istanbul_getProxiedValidators', - validating = 'istanbul_isValidating', - replicaState = 'istanbul_getCurrentReplicaState', -} - -const TMP_PATH = '/tmp/e2e' -const verbose = false - -describe('replica swap tests', () => { - const gethConfig: GethRunConfig = { - migrate: true, - runPath: TMP_PATH, - verbosity: 4, - networkId: 1101, - network: 'local', - genesisConfig: { - blockTime: 1, - churritoBlock: 0, - donutBlock: 0, - espressoBlock: 0, - }, - instances: [ - { - name: 'validator0', - validating: true, - syncmode: 'full', - port: 30303, - rpcport: 8545, - proxy: 'validator0-proxy0', - isProxied: true, - proxyport: 30304, - proxyAllowPrivateIp: true, - }, - { - name: 'validator0-proxy0', - isProxy: true, - validating: false, - syncmode: 'full', - proxyport: 30304, - port: 30305, - rpcport: 8546, - }, - { - name: 'validator1', - validating: true, - syncmode: 'full', - port: 30307, - rpcport: 8547, - }, - { - name: 'validator2', - validating: true, - syncmode: 'full', - port: 30309, - rpcport: 8549, - }, - { - name: 'validator3', - validating: true, - syncmode: 'full', - port: 30311, - wsport: 8544, - rpcport: 8551, - }, - { - name: 'validator4', - validating: true, - syncmode: 'full', - port: 30313, - rpcport: 8553, - }, - ], - } - const numValidators = gethConfig.instances.filter((x) => x.validating).length - - const hooks: any = getHooks(gethConfig) - let web3: Web3 - - before(async function (this: any) { - this.timeout(0) - // Comment out the following line after a local run for a quick rerun. - await hooks.before() - }) - - after(async function (this: any) { - this.timeout(0) - await hooks.after() - }) - - const restart = async () => { - await hooks.restart() - web3 = new Web3('http://localhost:8545') - } - - describe('replica behind single proxy', () => { - let epoch: number - let blockCount = 0 - let proxyRPC: RpcCaller - let validatoRPC: RpcCaller - let replicaRPC: RpcCaller - let swapBlock: number - const missed: any = [] - - before(async function (this: any) { - this.timeout(0) // Disable test timeout - - await restart() - - const proxyPubKey = privateKeyToPublicKey(gethConfig.instances[1].nodekey!) - const replica: GethInstanceConfig = { - name: 'validator0-replica0', - replica: true, - validating: true, - syncmode: 'full', - port: 30315, - rpcport: 8555, - privateKey: gethConfig.instances[0].privateKey, - minerValidator: privateKeyToAddress(gethConfig.instances[0].privateKey!), - proxy: 'validator0-proxy0', - isProxied: true, - proxyport: 30304, - proxyAllowPrivateIp: true, - proxies: [ - getEnodeAddress(proxyPubKey, '127.0.0.1', 30304), - getEnodeAddress(proxyPubKey, '127.0.0.1', 30305), - ], - } - - await initAndStartGeth(gethConfig, hooks.gethBinaryPath, replica, verbose) - if (verbose) { - console.info('Starting sync w/ replica') - } - await waitToFinishInstanceSyncing(replica) - if (verbose) { - console.info('Replica synced') - } - - epoch = 20 - // Wait for an epoch transition to ensure everyone is connected to one another. - await waitForEpochTransition(web3, epoch) - - const validatorWSWeb3Url = 'ws://localhost:8544' - const validatorWSWeb3 = new Web3(validatorWSWeb3Url) - - validatoRPC = new HttpRpcCaller(new Web3.providers.HttpProvider('http://localhost:8545')) - proxyRPC = new HttpRpcCaller(new Web3.providers.HttpProvider('http://localhost:8546')) - replicaRPC = new HttpRpcCaller(new Web3.providers.HttpProvider('http://localhost:8555')) - - const handled: any = {} - let errorMsg = '' - let setSwap = false - const recordNewBlock = async (header: BlockHeader) => { - try { - if (handled[header.number]) { - return - } - if (!setSwap) { - swapBlock = header.number + 40 - if (verbose) { - console.info(`Swapping validators at block ${swapBlock}`) - } - // tslint:disable-next-line: no-shadowed-variable - let resp = await replicaRPC.call(IstanbulManagement.startAtBlock, [swapBlock]) - assert.equal(resp.error, null) - resp = await validatoRPC.call(IstanbulManagement.stopAtBlock, [swapBlock]) - assert.equal(resp.error, null) - setSwap = true - } - handled[header.number] = true - blockCount += 1 - const bitmap = parseBlockExtraData(header.extraData).parentAggregatedSeal.bitmap - for (let i = 0; i < numValidators; i += 1) { - if (!bitIsSet(bitmap, i)) { - missed.push({ idx: i, num: header.number }) - } - } - } catch (e: any) { - console.error(e) - errorMsg = e - } - } - - // Wait for nodes to reliably sign blocks - await sleep(2 * epoch) - const subscription = validatorWSWeb3.eth.subscribe('newBlockHeaders') - subscription.on('data', recordNewBlock) - - // Wait for a few epochs while rotating a validator. - while (blockCount < 80) { - if (verbose) { - console.info(`Waiting. ${blockCount}/80`) - } - await sleep(epoch) - } - ;(subscription as any).unsubscribe() - if (verbose) { - console.info('Unsubscribed from block headers') - } - - // Wait for the current epoch to complete. - await sleep(epoch) - assert.equal(errorMsg, '') - }) - - it('replica is validating', async () => { - const validating = (await replicaRPC.call(IstanbulManagement.validating, [])).result as any - assert.isTrue(validating) - }) - - it('primary is not validating', async () => { - const validating = (await validatoRPC.call(IstanbulManagement.validating, [])).result as any - assert.isFalse(validating) - }) - - it('replica should have good val enode table', async () => { - const resp = (await replicaRPC.call(IstanbulManagement.valEnodeTableInfo, [])).result as any - Object.keys(resp).forEach((k) => { - const enode = resp[k].enode - assert.isTrue((enode || '') !== '') - }) - }) - - it('proxy should be connected', async () => { - const resp = (await proxyRPC.call(IstanbulManagement.proxiedValidators, [])) - .result as string[][] - assert.equal(resp.length, 2) - }) - - it('should switch without downtime', async () => { - if (missed.length !== 0) { - missed.forEach((x: any) => console.warn(`Validator idx ${x.idx} missed block ${x.num}`)) - console.warn(`Val idx 0 should have switched on block ${swapBlock}`) - } - assert.isBelow(missed.length, 4) - }) - }) -}) diff --git a/packages/celotool/src/e2e-tests/slashing_tests.ts b/packages/celotool/src/e2e-tests/slashing_tests.ts deleted file mode 100644 index 25303a783..000000000 --- a/packages/celotool/src/e2e-tests/slashing_tests.ts +++ /dev/null @@ -1,428 +0,0 @@ -// tslint:disable-next-line: no-reference (Required to make this work w/ ts-node) -import { NULL_ADDRESS } from '@celo/base/lib/address' -import { ContractKit, newKitFromWeb3 } from '@celo/contractkit' -import { ensureLeading0x } from '@celo/utils/lib/address' -import BigNumber from 'bignumber.js' -import { assert } from 'chai' -import * as _ from 'lodash' -import * as rlp from 'rlp' -import Web3 from 'web3' -import { GethRunConfig } from '../lib/interfaces/geth-run-config' -import { getHooks, sleep, waitForBlock } from './utils' - -const headerHex = - '0xf901a6a07285abd5b24742f184ad676e31f6054663b3529bc35ea2fcad8a3e0f642a46f7948888f1f195afa192cfee860698584c030f4c9db1a0ecc60e00b3fe5ce9f6e1a10e5469764daf51f1fe93c22ec3f9a7583a80357217a0d35d334d87c0cc0a202e3756bf81fae08b1575f286c7ee7a3f8df4f0f3afc55da056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001825208845c47775c80' - -const TMP_PATH = '/tmp/e2e' - -const safeMarginBlocks = 4 - -function headerArray(block: any) { - if (!block.nonce) { - // Before Gingerbread fork - return [ - block.parentHash, - block.miner, - block.stateRoot, - block.transactionsRoot, - block.receiptsRoot, - block.logsBloom, - block.number, - block.gasUsed, - block.timestamp, - block.extraData, - ] - } - return [ - block.parentHash, - block.sha3Uncles, - block.miner, - block.stateRoot, - block.transactionsRoot, - block.receiptsRoot, - block.logsBloom, - new BigNumber(block.difficulty).toNumber(), - block.number, - block.gasLimit, - block.gasUsed, - block.timestamp, - block.extraData, - block.mixHash, - block.nonce, - block.baseFee, - ] -} - -function headerFromBlock(block: any) { - return ensureLeading0x(rlp.encode(headerArray(block)).toString('hex')) -} - -// Find a validator that double signed. Both blocks will have signatures from exactly 2F+1 validators. -async function findDoubleSignerIndex( - kit: ContractKit, - header: string, - other: string -): Promise { - const slasher = await kit._web3Contracts.getDoubleSigningSlasher() - const bitmap1 = await slasher.methods.getVerifiedSealBitmapFromHeader(header).call() - const bitmap2 = await slasher.methods.getVerifiedSealBitmapFromHeader(other).call() - - let bmNum1 = new BigNumber(bitmap1).toNumber() - let bmNum2 = new BigNumber(bitmap2).toNumber() - bmNum1 = bmNum1 >> 1 - bmNum2 = bmNum2 >> 1 - let signerIdx = 1 - for (let i = 1; i < 5; i++) { - if ((bmNum1 & 1) === 1 && (bmNum2 & 1) === 1) { - break - } - signerIdx++ - bmNum1 = bmNum1 >> 1 - bmNum2 = bmNum2 >> 1 - } - return signerIdx -} - -async function generateValidIntervalArrays( - startBlock: number, - endBlock: number, - startEpoch: number, - slotSize: number, - kit: ContractKit -): Promise<{ - startBlocks: number[] - endBlocks: number[] -}> { - const startBlocks: number[] = [] - const endBlocks: number[] = [] - - const nextEpochStart = await kit.getFirstBlockNumberForEpoch(startEpoch + 1) - for (let currentSlotStart = startBlock; currentSlotStart <= endBlock; ) { - let currentSlotEnd = currentSlotStart + slotSize - 1 - currentSlotEnd = currentSlotEnd > endBlock ? endBlock : currentSlotEnd - // avoids crossing the epoch - currentSlotEnd = - currentSlotEnd >= nextEpochStart && currentSlotStart < nextEpochStart - ? nextEpochStart - 1 - : currentSlotEnd - startBlocks.push(currentSlotStart) - endBlocks.push(currentSlotEnd) - currentSlotStart = currentSlotEnd + 1 - } - - return { startBlocks, endBlocks } -} - -describe('slashing tests', function (this: any) { - const gethConfig: GethRunConfig = { - network: 'local', - networkId: 1101, - runPath: TMP_PATH, - migrate: true, - genesisConfig: { - churritoBlock: 0, - donutBlock: 0, - espressoBlock: 0, - }, - instances: [ - { - name: 'validator0', - validating: true, - syncmode: 'full', - port: 30303, - rpcport: 8545, - }, - { - name: 'validator1', - validating: true, - syncmode: 'full', - port: 30305, - rpcport: 8547, - }, - { - name: 'validator2', - validating: true, - syncmode: 'full', - port: 30307, - rpcport: 8549, - }, - { - name: 'validator3', - validating: true, - syncmode: 'full', - port: 30309, - rpcport: 8551, - }, - { - name: 'validator4', - validating: true, - syncmode: 'full', - port: 30311, - rpcport: 8553, - }, - ], - } - - // Do a shallow copy so that the instance objects are the the same (even after the init step fills private keys, etc.) - const gethConfigDown = _.clone(gethConfig) - // Exclude the last validator to simulate it being down - gethConfigDown.instances = gethConfig.instances.slice(0, gethConfig.instances.length - 1) - - const hooks: any = getHooks(gethConfig) - const hooksDown: any = getHooks(gethConfigDown) - let web3: Web3 - let kit: ContractKit - - before(async function (this: any) { - this.timeout(0) - await hooks.before() - }) - - after(async function (this: any) { - this.timeout(0) - await hooks.after() - }) - - const restart = async () => { - await hooks.restart() - web3 = new Web3('http://localhost:8545') - kit = newKitFromWeb3(web3) - await sleep(1) - } - - const restartWithDowntime = async () => { - await hooksDown.restart() - web3 = new Web3('http://localhost:8545') - kit = newKitFromWeb3(web3) - await sleep(1) - } - - describe('when running a network', () => { - before(async function (this: any) { - this.timeout(0) // Disable test timeout - await restartWithDowntime() - }) - - it('should parse blockNumber from test header', async () => { - this.timeout(0) - const contract = await kit._web3Contracts.getElection() - const blockNumber = await contract.methods.getBlockNumberFromHeader(headerHex).call() - assert.equal(blockNumber, '1') - }) - - it('should parse blockNumber from current header', async () => { - const contract = await kit._web3Contracts.getElection() - const current = await kit.connection.getBlockNumber() - const block = await kit.connection.getBlock(current) - const header = headerFromBlock(block) - const blockNumber = await contract.methods.getBlockNumberFromHeader(header).call() - assert.equal(blockNumber, current.toString()) - }) - - it('should hash test header correctly', async () => { - const contract = await kit._web3Contracts.getElection() - const hash = await contract.methods.hashHeader(headerHex).call() - assert.equal(hash, '0x2e14ef428293e41c5f81a108b5d36f892b2bee3e34aec4223474c4a31618ea69') - }) - - it('should hash current header correctly', async () => { - const contract = await kit._web3Contracts.getElection() - const current = await kit.connection.getBlockNumber() - const block = await kit.connection.getBlock(current) - const header = headerFromBlock(block) - const blockHash = await contract.methods.hashHeader(header).call() - assert.equal(blockHash, block.hash) - }) - }) - - let doubleSigningBlock: any - - describe('test slashing for downtime', () => { - before(async function (this: any) { - this.timeout(0) // Disable test timeout - await restartWithDowntime() - }) - - it('slash for downtime', async function (this: any) { - this.timeout(0) // Disable test timeout - const slasher = await kit._web3Contracts.getDowntimeSlasher() - const slashableDowntime = new BigNumber(await slasher.methods.slashableDowntime().call()) - await waitForBlock(web3, 1) - const blockNumber = await kit.connection.getBlockNumber() - await waitForBlock(web3, blockNumber + slashableDowntime.toNumber() + 2 * safeMarginBlocks) - - // Store this block for testing double signing - doubleSigningBlock = await kit.connection.getBlock(blockNumber + 2 * safeMarginBlocks) - - const signer = await slasher.methods.validatorSignerAddressFromSet(4, blockNumber).call() - const validator = (await kit.connection.getAccounts())[0] - await kit.connection.web3.eth.personal.unlockAccount(validator, '', 1000000) - const lockedGold = await kit.contracts.getLockedGold() - - const validatorsContract = await kit._web3Contracts.getValidators() - const history = await validatorsContract.methods.getMembershipHistory(signer).call() - const historyIndex = history[0].length - 1 - - const slotSize = slashableDowntime.dividedToIntegerBy(3).toNumber() - - const startBlock = blockNumber + safeMarginBlocks - const endBlock = startBlock + slashableDowntime.toNumber() - 1 - const startEpoch = await kit.getEpochNumberOfBlock(startBlock) - - const intervalArrays = await generateValidIntervalArrays( - startBlock, - endBlock, - startEpoch, - slotSize, - kit - ) - - for (let i = 0; i < intervalArrays.startBlocks.length; i += 1) { - await slasher.methods - .setBitmapForInterval(intervalArrays.startBlocks[i], intervalArrays.endBlocks[i]) - .send({ from: validator, gas: 5000000 }) - } - - await slasher.methods - .slash( - intervalArrays.startBlocks, - intervalArrays.endBlocks, - [4, 4], - historyIndex, - [], - [], - [], - [NULL_ADDRESS], - [NULL_ADDRESS], - [0] - ) - .send({ from: validator, gas: 5000000 }) - - const balance = await lockedGold.getAccountTotalLockedGold(signer) - // Penalty is defined to be 100 cGLD in migrations, locked gold is 10000 cGLD for a validator - assert.equal(balance.toString(10), '9900000000000000000000') - }) - }) - - describe('test slashing for downtime with contractkit', () => { - before(async function (this: any) { - this.timeout(0) // Disable test timeout - await restartWithDowntime() - }) - - it('slash for downtime with contractkit', async function (this: any) { - this.timeout(0) // Disable test timeout - const slasher = await kit.contracts.getDowntimeSlasher() - const blockNumber = await kit.connection.getBlockNumber() - const slashableDowntime = await slasher.slashableDowntime() - - await waitForBlock(web3, blockNumber + slashableDowntime + 2 * safeMarginBlocks) - - const user = (await kit.connection.getAccounts())[0] - await kit.connection.web3.eth.personal.unlockAccount(user, '', 1000000) - - const endBlock = blockNumber + safeMarginBlocks + slashableDowntime - 1 - const intervals = await slasher.slashableDowntimeIntervalsBefore(endBlock) - - for (const interval of intervals) { - await slasher.setBitmapForInterval(interval).send({ from: user, gas: 5000000 }) - } - - const election = await kit.contracts.getElection() - const signer = await election.validatorSignerAddressFromSet(4, intervals[0].start) - - const tx = await slasher.slashValidator(signer, intervals) - const txResult = await tx.send({ from: user, gas: 5000000 }) - const txRcpt = await txResult.waitReceipt() - assert.equal(txRcpt.status, true) - - const lockedGold = await kit.contracts.getLockedGold() - const balance = await lockedGold.getAccountTotalLockedGold(signer) - // Penalty is defined to be 100 cGLD in migrations, locked gold is 10000 cGLD for a validator - assert.equal(balance.toString(10), '9900000000000000000000') - }) - }) - - describe('test slashing for double signing', () => { - before(async function (this: any) { - this.timeout(0) // Disable test timeout - await restart() - }) - - it('slash for double signing', async function (this: any) { - this.timeout(0) // Disable test timeout - const slasher = await kit._web3Contracts.getDoubleSigningSlasher() - - await waitForBlock(web3, doubleSigningBlock.number) - - const other = headerFromBlock(doubleSigningBlock) - - const num = await slasher.methods.getBlockNumberFromHeader(other).call() - - const header = headerFromBlock(await kit.connection.getBlock(num)) - - const signerIdx = await findDoubleSignerIndex(kit, header, other) - const signer = await slasher.methods.validatorSignerAddressFromSet(signerIdx, num).call() - const validator = (await kit.connection.getAccounts())[0] - await kit.connection.web3.eth.personal.unlockAccount(validator, '', 1000000) - - const lockedGold = await kit.contracts.getLockedGold() - const validatorsContract = await kit._web3Contracts.getValidators() - const history = await validatorsContract.methods.getMembershipHistory(signer).call() - const historyIndex = history[0].length - 1 - - await slasher.methods - .slash( - signer, - signerIdx, - header, - other, - historyIndex, - [], - [], - [], - [NULL_ADDRESS], - [NULL_ADDRESS], - [0] - ) - .send({ from: validator, gas: 5000000 }) - - // Penalty is defined to be 9000 cGLD in migrations, locked gold is 10000 cGLD for a validator, so after slashing locked gold is 1000cGld - const balance = await lockedGold.getAccountTotalLockedGold(signer) - assert.equal(balance.toString(10), '1000000000000000000000') - }) - }) - - describe('test slashing for double signing with contractkit', () => { - before(async function (this: any) { - this.timeout(0) // Disable test timeout - await restart() - }) - - it('slash for double signing with contractkit', async function (this: any) { - this.timeout(0) // Disable test timeout - const slasher = await kit.contracts.getDoubleSigningSlasher() - const election = await kit.contracts.getElection() - await waitForBlock(web3, doubleSigningBlock.number) - - const other = headerFromBlock(doubleSigningBlock) - const num = await slasher.getBlockNumberFromHeader(other) - const header = headerFromBlock(await kit.connection.getBlock(num)) - const signerIdx = await findDoubleSignerIndex(kit, header, other) - const signer = await election.validatorSignerAddressFromSet(signerIdx, num) - - const validator = (await kit.connection.getAccounts())[0] - await kit.connection.web3.eth.personal.unlockAccount(validator, '', 1000000) - - const tx = await slasher.slashSigner(signer, header, other) - const txResult = await tx.send({ from: validator, gas: 5000000 }) - const txRcpt = await txResult.waitReceipt() - assert.equal(txRcpt.status, true) - - // Penalty is defined to be 9000 cGLD in migrations, locked gold is 10000 cGLD for a validator, so after slashing locked gold is 1000cGld - const lockedGold = await kit.contracts.getLockedGold() - const balance = await lockedGold.getAccountTotalLockedGold(signer) - assert.equal(balance.toString(10), '1000000000000000000000') - }) - }) -}) diff --git a/packages/celotool/src/e2e-tests/sync_tests.ts b/packages/celotool/src/e2e-tests/sync_tests.ts deleted file mode 100644 index b998be8fe..000000000 --- a/packages/celotool/src/e2e-tests/sync_tests.ts +++ /dev/null @@ -1,169 +0,0 @@ -// tslint:disable: no-console -import { assert } from 'chai' -import Web3 from 'web3' -import { GethInstanceConfig } from '../lib/interfaces/geth-instance-config' -import { GethRunConfig } from '../lib/interfaces/geth-run-config' -import { getHooks, initAndSyncGethWithRetry, killInstance, waitForBlock } from './utils' - -const TMP_PATH = '/tmp/e2e' -const verbose = false - -describe('sync tests', function (this: any) { - this.timeout(0) - - const gethConfig: GethRunConfig = { - networkId: 1101, - network: 'local', - runPath: TMP_PATH, - migrate: true, - verbosity: 2, - genesisConfig: { - churritoBlock: 0, - donutBlock: 0, - espressoBlock: 0, - }, - instances: [ - { - name: 'validator0', - validating: true, - syncmode: 'full', - port: 30303, - rpcport: 8545, - }, - { - name: 'validator1', - validating: true, - syncmode: 'full', - port: 30305, - rpcport: 8547, - }, - { - name: 'validator2', - validating: true, - syncmode: 'full', - port: 30307, - rpcport: 8549, - }, - { - name: 'validator3', - validating: true, - syncmode: 'full', - port: 30309, - rpcport: 8551, - }, - ], - } - - const fullNode: GethInstanceConfig = { - name: 'txfull', - validating: false, - syncmode: 'full', - lightserv: true, - port: 30311, - rpcport: 8553, - } - - const hooks = getHooks(gethConfig) - - before(async function (this: any) { - this.timeout(0) - // Start validator nodes and migrate contracts. - await hooks.before() - // Restart validator nodes. - await hooks.restart() - await initAndSyncGethWithRetry( - gethConfig, - hooks.gethBinaryPath, - fullNode, - [...gethConfig.instances, fullNode], - verbose, - 3 - ) - }) - - after(async function (this: any) { - this.timeout(0) - await hooks.after() - }) - - const syncModes = ['full', 'fast', 'light', 'lightest'] - for (const syncmode of syncModes) { - describe(`when syncing with a ${syncmode} node`, () => { - let syncNode: GethInstanceConfig - - beforeEach(async () => { - syncNode = { - name: syncmode, - validating: false, - syncmode, - port: 30313, - wsport: 9555, - rpcport: 8555, - lightserv: syncmode !== 'light' && syncmode !== 'lightest', - } - await initAndSyncGethWithRetry( - gethConfig, - hooks.gethBinaryPath, - syncNode, - [fullNode, syncNode], - verbose, - 3 - ) - }) - - afterEach(() => killInstance(syncNode)) - - it('should sync the latest block', async () => { - const validatingWeb3 = new Web3(`http://localhost:8545`) - const validatingFirstBlock = await validatingWeb3.eth.getBlockNumber() - console.log(`At block ${validatingFirstBlock}, waiting for next block`) - await waitForBlock(validatingWeb3, validatingFirstBlock + 1) - const validatingLatestBlock = await validatingWeb3.eth.getBlockNumber() - - const syncWeb3 = new Web3(`http://localhost:8555`) - console.log(`Waiting to sync to block ${validatingFirstBlock}`) - await waitForBlock(syncWeb3, validatingLatestBlock) - const syncLatestBlock = await syncWeb3.eth.getBlockNumber() - - assert.isAbove(validatingLatestBlock, 1) - // Assert that the validator is still producing blocks. - assert.isAbove(validatingLatestBlock, validatingFirstBlock) - // Assert that the syncing node has synced with the validator. - assert.isAtLeast(syncLatestBlock, validatingLatestBlock) - }) - }) - } - describe(`when a validator's data directory is deleted`, () => { - beforeEach(async function (this: any) { - this.timeout(0) // Disable test timeout - await hooks.restart() - }) - - it('should continue to block produce', async function (this: any) { - this.timeout(0) - const instance: GethInstanceConfig = gethConfig.instances[1] - await killInstance(instance) - // copy instance - const additionalInstance = { ...instance } - await initAndSyncGethWithRetry( - gethConfig, - hooks.gethBinaryPath, - additionalInstance, - [gethConfig.instances[0], additionalInstance], - verbose, - 3 - ) - - const web3 = new Web3(`http://localhost:${additionalInstance.rpcport}`) - const address = (await web3.eth.getAccounts())[0] - const currentBlock = await web3.eth.getBlock('latest') - for (let i = 1; i < 500; i++) { - await waitForBlock(web3, currentBlock.number + i) - if ((await web3.eth.getBlock(currentBlock.number + i)).miner === address) { - return // A block proposed by validator who lost randomness was found, hence randomness was recovered - } - } - assert.fail('Reset validator did not propose any new blocks') - }) - }) -}) diff --git a/packages/celotool/src/e2e-tests/transfer_tests.ts b/packages/celotool/src/e2e-tests/transfer_tests.ts deleted file mode 100644 index d465fdfb3..000000000 --- a/packages/celotool/src/e2e-tests/transfer_tests.ts +++ /dev/null @@ -1,940 +0,0 @@ -// tslint:disable-next-line: no-reference (Required to make this work w/ ts-node) -import { CeloTxPending, CeloTxReceipt, TransactionResult } from '@celo/connect' -import { ContractKit, newKitFromWeb3 } from '@celo/contractkit' -import { CeloTokenType, EachCeloToken, StableToken, Token } from '@celo/contractkit/lib/celo-tokens' -import { eqAddress, toChecksumAddress } from '@celo/utils/lib/address' -import { toFixed } from '@celo/utils/lib/fixidity' -import BigNumber from 'bignumber.js' -import { assert } from 'chai' -import Web3 from 'web3' -import { GethInstanceConfig } from '../lib/interfaces/geth-instance-config' -import { GethRunConfig } from '../lib/interfaces/geth-run-config' -import { getHooks, initAndSyncGethWithRetry, killInstance, sleep } from './utils' - -const TMP_PATH = '/tmp/e2e' -const verbose = false - -/** - * Helper Class to change StableToken Inflation in tests - */ -class InflationManager { - private kit: ContractKit - private readonly minUpdateDelay = 10 - - constructor( - readonly validatorUri: string, - readonly validatorAddress: string, - readonly token: StableToken - ) { - this.kit = newKitFromWeb3(new Web3(validatorUri)) - this.kit.connection.defaultAccount = validatorAddress - } - - now = async (): Promise => { - return Number((await this.kit.connection.getBlock('pending')).timestamp) - } - - getNextUpdateRate = async (): Promise => { - const stableToken = await this.getStableToken() - // Compute necessary `updateRate` so inflationFactor adjusment takes place on next operation - const { factorLastUpdated } = await stableToken.getInflationParameters() - - // Wait until the minimum update delay has passed so we can set a rate that gives us some - // buffer time to make the transaction in the next availiable update window. - let timeSinceLastUpdated = (await this.now()) - factorLastUpdated.toNumber() - while (timeSinceLastUpdated < this.minUpdateDelay) { - await sleep(this.minUpdateDelay - timeSinceLastUpdated) - timeSinceLastUpdated = (await this.now()) - factorLastUpdated.toNumber() - } - - return timeSinceLastUpdated - } - - getParameters = async () => { - const stableToken = await this.getStableToken() - return stableToken.getInflationParameters() - } - - setInflationRateForNextTransfer = async (rate: BigNumber) => { - // Possibly update the inflation factor and ensure it won't update again. - await this.setInflationParameters(new BigNumber(1), Number.MAX_SAFE_INTEGER) - - const updateRate = await this.getNextUpdateRate() - await this.setInflationParameters(rate, updateRate) - } - - setInflationParameters = async (rate: BigNumber, updatePeriod: number) => { - const stableToken = await this.getStableToken() - await stableToken - .setInflationParameters(toFixed(rate).toFixed(), updatePeriod.toFixed()) - .sendAndWaitForReceipt({ from: this.validatorAddress }) - } - - getStableToken = async () => { - return this.kit.celoTokens.getWrapper(this.token) - } -} - -const setIntrinsicGas = async (validatorUri: string, validatorAddress: string, gasCost: number) => { - const kit = newKitFromWeb3(new Web3(validatorUri)) - const parameters = await kit.contracts.getBlockchainParameters() - await parameters - .setIntrinsicGasForAlternativeFeeCurrency(gasCost.toString()) - .sendAndWaitForReceipt({ from: validatorAddress }) -} - -// Intrinsic gas for a basic transaction -const INTRINSIC_TX_GAS_COST = 21000 - -// Additional intrinsic gas for a transaction with fee currency specified -const ADDITIONAL_INTRINSIC_TX_GAS_COST = 50000 - -// If the To address has zero as the balance, the cost of writting that address is -const sstoreSetGasEIP2200 = 20000 -const sstoreResetGasEIP2200 = 5000 -const coldSloadCostEIP2929 = 800 // The Eip2929 set this to 2100, but our Cip48 back to 800 -const coldAccountAccessCostEIP2929 = 900 // The Eip2929 set this to 2600, but our Cip48 back to 900 -const warmStorageReadCostEIP2929 = 100 // Eip2929 and Cip48 - -// This number represent the gasUsed in the execution of the StableToken transfer assuming: -// - Nothing was preloaded in the state accessList, so the first storage calls will cost: -// * ColdSloadCostEIP2929 = 800 -// * ColdAccountAccessCostEIP2929 = 900 -// - The From and To address -// * HAVE funds -// * non of those will be zero after the transfer -// * non those were modified before (as part of the same tx) -// * This means that both SSTORE (From and To) will cost: -// SstoreResetGasEIP2200 [5000] - ColdSloadCostEIP2929 [800] => 4200 -// - No intrinsic gas involved BUT 630 gas charged for the amount of bytes sent -const basicStableTokenTransferGasCost = 31253 - -// As the basicStableTokenTransferGasCost assumes that the transfer TO have funds, we should -// only add the difference to calculate the gas (sstoreSetGasEIP2200 - 4200) => 15800 -const emptyFundsBeforeForBasicCalc = - sstoreSetGasEIP2200 - (sstoreResetGasEIP2200 - coldSloadCostEIP2929) // 15800 - -// The StableToken transfer, paid with the same StableToken, preloads a lot of state -// when the fee is subsctracted from the account, which generates that the basicStableTokenTransferGasCost -// cost less. The actual differences: -// - SLOADS ColdSloadCostEIP2929 -> WarmStorageReadCostEIP2929 (-700 each) -// * 6 from the stableToken contract -// * 2 from the celoRegistry contract -// * 2 from the Freeze contract -// - Account Check ( EXTCODEHASH | EXTCODESIZE | ext BALANCE) -// coldAccountAccessCostEIP2929 -> WarmStorageReadCostEIP2929 (-800 each) -// * 3 from the stableToken contract -// * 1 from the celoRegistry contract -// * 1 from the Freeze contract -// - The From account as already modified the state for that address -// * This will make that instead of SstoreResetGasEIP2200 [5000] - ColdSloadCostEIP2929 [800] => 4200 -// will cost WarmStorageReadCostEIP2929 [100] (-4100) -const savingGasStableTokenTransferPaidWithSameStable = - (coldSloadCostEIP2929 - warmStorageReadCostEIP2929) * 10 + - (coldAccountAccessCostEIP2929 - warmStorageReadCostEIP2929) * 5 + - (sstoreResetGasEIP2200 - coldSloadCostEIP2929 - warmStorageReadCostEIP2929) // 15100 - -/** Helper to watch balance changes over accounts */ -interface BalanceWatcher { - update(): Promise - - delta(address: string, token: CeloTokenType): BigNumber - - current(address: string, token: CeloTokenType): BigNumber - - initial(address: string, token: CeloTokenType): BigNumber - - debugPrint(address: string, token: CeloTokenType): void -} - -async function newBalanceWatcher(kit: ContractKit, accounts: string[]): Promise { - async function fetch() { - const balances: Record> = {} - await Promise.all( - accounts.map(async (a) => { - balances[a] = await kit.celoTokens.balancesOf(a) - }) - ) - return balances - } - - const initial = await fetch() - let current = initial - return { - async update() { - current = await fetch() - }, - delta(address: string, token: CeloTokenType) { - return (current[address][token] || new BigNumber(0)).minus(initial[address][token] || 0) - }, - current(address: string, token: CeloTokenType) { - return current[address][token] || new BigNumber(0) - }, - initial(address: string, token: CeloTokenType) { - return initial[address][token] || new BigNumber(0) - }, - debugPrint(address: string, token: CeloTokenType) { - // tslint:disable-next-line: no-console - console.log({ - initial: initial[address][token]?.toString(), - current: current[address][token]?.toString(), - delta: (current[address][token] || new BigNumber(0)) - .minus(initial[address][token] || 0) - .toString(), - }) - }, - } -} - -function assertEqualBN(value: BigNumber, expected: BigNumber) { - assert.equal(value.toString(), expected.toString()) -} - -describe('Transfer tests', function (this: any) { - this.timeout(0) - - let kit: ContractKit - const TransferAmount: BigNumber = new BigNumber(Web3.utils.toWei('1', 'ether')) - - let currentGethInstance: GethInstanceConfig - - let governanceAddress: string // set later on using the contract itself - const validatorAddress = '0x47e172f6cfb6c7d01c1574fa3e2be7cc73269d95' - const DEF_FROM_PK = 'f2f48ee19680706196e2e339e5da3491186e0c4c5030670656b0e0164837257d' - const FromAddress = '0x5409ed021d9299bf6814279a6a1411a7e866a631' - - // Arbitrary addresses. - const txFeeRecipientAddress = '0x5555555555555555555555555555555555555555' - const ToAddress = '0xbBae99F0E1EE565404465638d40827b54D343638' - const gatewayFeeRecipientAddress = '0x4f5f8a3f45d179553e7b95119ce296010f50f6f1' - - const syncModes = ['full', 'fast', 'light', 'lightest'] - const gethConfig: GethRunConfig = { - migrate: true, - networkId: 1101, - network: 'local', - runPath: TMP_PATH, - genesisConfig: { - churritoBlock: 0, - donutBlock: 0, - espressoBlock: 0, - }, - instances: [ - { - name: 'validator', - validating: true, - minerValidator: validatorAddress, - // Separate address for tx fees, so that we can easy identify balance changes due to them - txFeeRecipient: txFeeRecipientAddress, - syncmode: 'full', - port: 30303, - rpcport: 8545, - }, - ], - } - - const hooks = getHooks(gethConfig) - - before(async function (this: any) { - this.timeout(0) - await hooks.before() - }) - - after(async function (this: any) { - this.timeout(0) - await hooks.after() - }) - - // Spin up a node that we can sync with. - const fullInstance: GethInstanceConfig = { - name: 'txFull', - validating: false, - syncmode: 'full', - lightserv: true, - gatewayFee: new BigNumber(10000), - port: 30305, - rpcport: 8547, - // We need to set an etherbase here so that the full node will accept transactions from - // light clients. - minerValidator: gatewayFeeRecipientAddress, - txFeeRecipient: gatewayFeeRecipientAddress, - } - - const restartWithCleanNodes = async () => { - await hooks.restart() - - kit = newKitFromWeb3(new Web3('http://localhost:8545')) - kit.connection.defaultGasInflationFactor = 1 - - // TODO(mcortesi): magic sleep. without it unlockAccount sometimes fails - await sleep(2) - // Assuming empty password - await kit.connection.web3.eth.personal.unlockAccount(validatorAddress, '', 1000000) - - await initAndSyncGethWithRetry( - gethConfig, - hooks.gethBinaryPath, - fullInstance, - [...gethConfig.instances, fullInstance], - verbose, - 3 - ) - - governanceAddress = (await kit._web3Contracts.getGovernance()).options.address - // The tests below check the balance of the governance contract (i.e. the community fund) - // before and after transactions to verify the correct amount has been received from the fees. - // This causes flakiness due to the fund also receiving epoch rewards (if the epoch change is - // between the blocks the balance checker uses as its before and after the test will fail due - // to the unexpected change from the epoch rewards). - // To avoid this, we set the community fund's fraction of epoch rewards to zero. - // Another option would have been to make the epoch size large enough so no epoch changes happen - // during the test. - const epochRewards = await kit._web3Contracts.getEpochRewards() - await epochRewards.methods.setCommunityRewardFraction(0).send({ from: validatorAddress }) - - // Give the account we will send transfers as sufficient gold and dollars. - const startBalance = TransferAmount.times(500) - const resDollars = await transferCeloDollars(validatorAddress, FromAddress, startBalance) - const resGold = await transferCeloGold(validatorAddress, FromAddress, startBalance) - await Promise.all([resDollars.waitReceipt(), resGold.waitReceipt()]) - } - - const startSyncNode = async (syncmode: string) => { - if (currentGethInstance != null) { - await killInstance(currentGethInstance) - } - - const light = syncmode === 'light' || syncmode === 'lightest' - currentGethInstance = { - name: syncmode, - validating: false, - syncmode, - port: 30307, - rpcport: 8549, - lightserv: !light, - // TODO(nategraf): Remove this when light clients can query for gateway fee. - gatewayFee: light ? new BigNumber(10000) : undefined, - privateKey: DEF_FROM_PK, - } - - // Spin up the node to run transfers as. - await initAndSyncGethWithRetry( - gethConfig, - hooks.gethBinaryPath, - currentGethInstance, - [fullInstance, currentGethInstance], - verbose, - 3 - ) - - // Reset contracts to send RPCs through transferring node. - kit.connection.setProvider(new Web3.providers.HttpProvider('http://localhost:8549')) - - // Give the node time to sync the latest block. - const upstream = await new Web3('http://localhost:8545').eth.getBlock('latest') - while ((await kit.connection.getBlock('latest')).number < upstream.number) { - await sleep(0.5) - } - - // Unlock Node account - await kit.connection.web3.eth.personal.unlockAccount(FromAddress, '', 1000000) - } - - const transferCeloGold = async ( - fromAddress: string, - toAddress: string, - amount: BigNumber, - txOptions: { - gas?: number - gasPrice?: string - feeCurrency?: string - gatewayFeeRecipient?: string - gatewayFee?: string - } = {} - ) => { - const res = await kit.connection.sendTransaction({ - from: fromAddress, - to: toAddress, - value: amount.toString(), - ...txOptions, - }) - return res - } - - const transferCeloDollars = async ( - fromAddress: string, - toAddress: string, - amount: BigNumber, - txOptions: { - gas?: number - gasPrice?: string - feeCurrency?: string - gatewayFeeRecipient?: string - gatewayFee?: string - } = {} - ) => { - const kitStableToken = await kit.contracts.getStableToken() - const res = await kitStableToken.transfer(toAddress, amount.toString()).send({ - from: fromAddress, - ...txOptions, - }) - - return res - } - - const getGasPriceMinimum = async (feeCurrency: string | undefined) => { - const gasPriceMinimum = await kit._web3Contracts.getGasPriceMinimum() - if (feeCurrency) { - return gasPriceMinimum.methods.getGasPriceMinimum(feeCurrency).call() - } else { - return gasPriceMinimum.methods.gasPriceMinimum().call() - } - } - - interface Fees { - total: BigNumber - tip: BigNumber - base: BigNumber - gateway: BigNumber - } - - interface GasUsage { - used?: number - expected: number - } - - interface TestTxResults { - ok: boolean - fees: Fees - gas: GasUsage - events: any[] - } - - const TRANSFER_TOPIC = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef' - - function truncateTopic(hex: string) { - return '0x' + hex.substring(26) - } - - function parseEvents(receipt: CeloTxReceipt | undefined) { - if (!receipt) { - return [] - } - if (receipt.events && receipt.events.Transfer) { - let events: any = receipt.events.Transfer - if (!(events instanceof Array)) { - events = [events] - } - return events.map((a: any) => ({ to: a.returnValues.to, from: a.returnValues.from })) - } - if (receipt.logs) { - return receipt.logs - .filter((a) => a.topics[0] === TRANSFER_TOPIC) - .map((a) => ({ to: truncateTopic(a.topics[2]), from: truncateTopic(a.topics[1]) })) - } - } - - const runTestTransaction = async ( - txResult: TransactionResult, - expectedGasUsed: number, - feeCurrency?: string - ): Promise => { - const minGasPrice = await getGasPriceMinimum(feeCurrency) - assert.isAbove(parseInt(minGasPrice, 10), 0) - - let ok = false - let receipt: CeloTxReceipt | undefined - try { - receipt = await txResult.waitReceipt() - ok = true - } catch (err) { - ok = false - } - - const events = parseEvents(receipt) - - if (receipt != null && receipt.gasUsed !== expectedGasUsed) { - // tslint:disable-next-line: no-console - console.log('OOPSS: Different Gas', receipt.gasUsed, expectedGasUsed) - } - - const gasVal = receipt ? receipt.gasUsed : expectedGasUsed - assert.isAbove(gasVal, 0) - const txHash = await txResult.getHash() - const tx: CeloTxPending = await kit.connection.getTransaction(txHash) - assert.isAbove(parseInt(tx.gasPrice, 10), 0) - const txFee = new BigNumber(gasVal).times(tx.gasPrice) - const txFeeBase = new BigNumber(gasVal).times(minGasPrice) - const txFeeTip = txFee.minus(txFeeBase) - const gatewayFee = new BigNumber(tx.gatewayFee || 0) - assert.equal(tx.gatewayFeeRecipient === null, gatewayFee.eq(0)) - - const fees: Fees = { - total: txFee.plus(gatewayFee), - base: txFeeBase, - tip: txFeeTip, - gateway: gatewayFee, - } - const gas: GasUsage = { - used: receipt && receipt.gasUsed, - expected: expectedGasUsed, - } - return { ok, fees, gas, events } - } - - function testTxPoolFiltering({ - feeToken, - gas, - expectedError, - }: { - feeToken: CeloTokenType - gas: number - expectedError: string - }) { - it('should not add the transaction to the pool', async () => { - const feeCurrency = await kit.celoTokens.getFeeCurrencyAddress(feeToken) - try { - const res = await transferCeloGold(FromAddress, ToAddress, TransferAmount, { - gas, - feeCurrency, - }) - await res.waitReceipt() - assert.fail('no error was thrown') - } catch (error: any) { - assert.include(error.toString(), expectedError) - } - }) - } - - const toTemplate = '0xbBae99F0E1EE565404465638d40827b54D343' // last 3 hex digits trimmed - // Starts with 1, otherwise the address could have the last byte as 00 which would change - // the gas consumption - let toCounter = 1 - - function generateCleanAddress(): string { - toCounter += 1 - // avoid the '00' at the end (check toCounter comment) - toCounter = toCounter % 100 === 0 ? toCounter + 1 : toCounter - - return toChecksumAddress(toTemplate + toCounter.toString().padStart(3, '0')) - } - - function testTwiceFirstAndSecondFundToANewAddress(testObject: { - transferToken: CeloTokenType - feeToken: CeloTokenType - expectedGas: number - expectSuccess?: boolean - txOptions?: { - gas?: number - gatewayFeeRecipient?: string - gatewayFee?: string - } - fromAddress?: string - toAddress?: string - }) { - const expectedGasAux = testObject.expectedGas - testObject.toAddress = generateCleanAddress() - // Add the fee to save to an empty address - testObject.expectedGas += emptyFundsBeforeForBasicCalc - describe('first fund to the To account', () => { - testTransferToken(testObject) - }) - testObject.expectedGas = expectedGasAux - describe('second fund to the To account', () => { - testTransferToken(testObject) - }) - } - - function testTransferToken({ - transferToken, - feeToken, - expectedGas, - txOptions, - expectSuccess = true, - fromAddress = FromAddress, - toAddress = ToAddress, - }: { - transferToken: CeloTokenType - feeToken: CeloTokenType - expectedGas: number - expectSuccess?: boolean - txOptions?: { - gas?: number - gatewayFeeRecipient?: string - gatewayFee?: string - } - fromAddress?: string - toAddress?: string - }) { - let txRes: TestTxResults - let balances: BalanceWatcher - - before(async () => { - const feeCurrency = await kit.celoTokens.getFeeCurrencyAddress(feeToken) - - const accounts = [ - fromAddress, - toAddress, - txFeeRecipientAddress, - gatewayFeeRecipientAddress, - governanceAddress, - ] - balances = await newBalanceWatcher(kit, accounts) - - const transferFn = transferToken === StableToken.cUSD ? transferCeloDollars : transferCeloGold - const txResult = await transferFn(fromAddress, toAddress, TransferAmount, { - ...txOptions, - feeCurrency, - }) - - txRes = await runTestTransaction(txResult, expectedGas, feeCurrency) - - await balances.update() - }) - - if (expectSuccess) { - it(`should succeed`, () => assert.isTrue(txRes.ok)) - - it(`should use the expected amount of gas`, () => - assert.equal(txRes.gas.used, txRes.gas.expected)) - - it(`should increment the receiver's ${transferToken} balance by the transfer amount`, () => - assertEqualBN(balances.delta(toAddress, transferToken), TransferAmount)) - - it('should have emitted transfer events for the fee token if not using CELO', () => { - if (kit.celoTokens.isStableToken(feeToken)) { - assert( - txRes.events.find( - (a) => eqAddress(a.to, governanceAddress) && eqAddress(a.from, fromAddress) - ) - ) - } - }) - - if (transferToken === feeToken) { - it(`should decrement the sender's ${transferToken} balance by the transfer amount plus fees`, () => { - const expectedBalanceChange = txRes.fees.total.plus(TransferAmount) - assertEqualBN(balances.delta(fromAddress, transferToken).negated(), expectedBalanceChange) - }) - } else { - it(`should decrement the sender's ${transferToken} balance by the transfer amount`, () => - assertEqualBN(balances.delta(fromAddress, transferToken).negated(), TransferAmount)) - - it(`should decrement the sender's ${feeToken} balance by the total fees`, () => - assertEqualBN(balances.delta(fromAddress, feeToken).negated(), txRes.fees.total)) - } - } else { - it(`should fail`, () => assert.isFalse(txRes.ok)) - - it(`should decrement the sender's ${feeToken} balance by the total fees`, () => - assertEqualBN(balances.delta(fromAddress, feeToken).negated(), txRes.fees.total)) - - it(`should not change the receiver's ${transferToken} balance`, () => { - assertEqualBN( - balances.initial(toAddress, transferToken), - balances.current(toAddress, transferToken) - ) - }) - - if (transferToken !== feeToken) { - it(`should not change the sender's ${transferToken} balance`, () => { - assertEqualBN( - balances.initial(fromAddress, transferToken), - balances.current(fromAddress, transferToken) - ) - }) - } - } - - it(`should increment the gateway fee recipient's ${feeToken} balance by the gateway fee`, () => - assertEqualBN(balances.delta(gatewayFeeRecipientAddress, feeToken), txRes.fees.gateway)) - - it(`should increment the infrastructure fund's ${feeToken} balance by the base portion of the gas fee`, () => - assertEqualBN(balances.delta(governanceAddress, feeToken), txRes.fees.base)) - - it(`should increment the tx fee recipient's ${feeToken} balance by the rest of the gas fee`, () => { - assertEqualBN(balances.delta(txFeeRecipientAddress, feeToken), txRes.fees.tip) - }) - } - describe('Normal Transfer >', () => { - before(restartWithCleanNodes) - - for (const syncMode of syncModes) { - describe(`${syncMode} Node >`, () => { - before(`start geth on sync: ${syncMode}`, () => startSyncNode(syncMode)) - - describe('Transfer CeloGold >', () => { - describe('with feeCurrency = CeloGold >', () => { - if (syncMode === 'light' || syncMode === 'lightest') { - describe('when running in light/lightest sync mode', () => { - const recipient = (choice: string) => { - switch (choice) { - case 'peer': - return gatewayFeeRecipientAddress - case 'random': - return Web3.utils.randomHex(20) - default: - // unset - return undefined - } - } - const feeValue = (choice: string) => { - switch (choice) { - case 'sufficient': - return '0x10000' - case 'insufficient': - return '0x1' - default: - // unset - return undefined - } - } - for (const recipientChoice of ['peer', 'random', 'unset']) { - describe(`when the gateway fee recipient is ${recipientChoice}`, () => { - for (const feeValueChoice of ['sufficient', 'insufficient', 'unset']) { - describe(`when the gateway fee value is ${feeValueChoice}`, () => { - const txOptions = { - gatewayFeeRecipient: recipient(recipientChoice), - gatewayFee: feeValue(feeValueChoice), - } - if (recipientChoice === 'random' || feeValueChoice === 'insufficient') { - it('should get rejected by the sending node before being added to the tx pool', async () => { - try { - const res = await transferCeloGold( - FromAddress, - ToAddress, - TransferAmount, - txOptions - ) - await res.waitReceipt() - assert.fail('no error was thrown') - } catch (error: any) { - assert.include(error.toString(), `Error: no suitable peers available`) - } - }) - } else { - testTransferToken({ - expectedGas: INTRINSIC_TX_GAS_COST, - transferToken: Token.CELO, - feeToken: Token.CELO, - txOptions, - }) - } - }) - } - }) - } - }) - } else { - testTransferToken({ - expectedGas: INTRINSIC_TX_GAS_COST, - transferToken: Token.CELO, - feeToken: Token.CELO, - }) - } - }) - - describe('feeCurrency = CeloDollars >', () => { - const intrinsicGas = INTRINSIC_TX_GAS_COST + ADDITIONAL_INTRINSIC_TX_GAS_COST - - describe('when there is no demurrage', () => { - describe('when setting a gas amount greater than the amount of gas necessary', () => - testTransferToken({ - expectedGas: intrinsicGas, - transferToken: Token.CELO, - feeToken: StableToken.cUSD, - })) - - describe('when setting a gas amount less than the intrinsic gas amount', () => { - it('should not add the transaction to the pool', async () => { - const gas = intrinsicGas - 1 - const feeCurrency = await kit.celoTokens.getFeeCurrencyAddress(StableToken.cUSD) - try { - const res = await transferCeloGold(FromAddress, ToAddress, TransferAmount, { - gas, - feeCurrency, - }) - await res.getHash() - assert.fail('no error was thrown') - } catch (error: any) { - assert.include(error.toString(), 'Error: intrinsic gas too low') - } - }) - }) - }) - }) - }) - - describe('Transfer CeloDollars', () => { - describe('feeCurrency = CeloDollars >', () => { - testTwiceFirstAndSecondFundToANewAddress({ - expectedGas: - basicStableTokenTransferGasCost + - INTRINSIC_TX_GAS_COST + - ADDITIONAL_INTRINSIC_TX_GAS_COST - - savingGasStableTokenTransferPaidWithSameStable, - transferToken: StableToken.cUSD, - feeToken: StableToken.cUSD, - }) - }) - - describe('feeCurrency = CeloGold >', () => { - testTwiceFirstAndSecondFundToANewAddress({ - expectedGas: basicStableTokenTransferGasCost + INTRINSIC_TX_GAS_COST, - transferToken: StableToken.cUSD, - feeToken: Token.CELO, - }) - }) - }) - }) - } - }) - - describe('Transfer with changed intrinsic gas cost >', () => { - const changedIntrinsicGasForAlternativeFeeCurrency = 34000 - - before(restartWithCleanNodes) - - for (const syncMode of syncModes) { - describe(`${syncMode} Node >`, () => { - before(`start geth on sync: ${syncMode}`, async () => { - try { - await startSyncNode(syncMode) - await setIntrinsicGas( - 'http://localhost:8545', - validatorAddress, - changedIntrinsicGasForAlternativeFeeCurrency - ) - } catch (err) { - console.debug('some error', err) - } - }) - - describe('Transfer CeloGold >', () => { - describe('feeCurrency = CeloDollars >', () => { - const intrinsicGas = - changedIntrinsicGasForAlternativeFeeCurrency + INTRINSIC_TX_GAS_COST - describe('when there is no demurrage', () => { - describe('when setting a gas amount greater than the amount of gas necessary', () => - testTransferToken({ - expectedGas: intrinsicGas, - transferToken: Token.CELO, - feeToken: StableToken.cUSD, - })) - - describe('when setting a gas amount less than the intrinsic gas amount', () => { - testTxPoolFiltering({ - gas: intrinsicGas - 1, - feeToken: StableToken.cUSD, - expectedError: 'Error: intrinsic gas too low', - }) - }) - }) - }) - }) - - describe('Transfer CeloDollars', () => { - describe('feeCurrency = CeloDollars >', () => { - testTwiceFirstAndSecondFundToANewAddress({ - expectedGas: - basicStableTokenTransferGasCost + - changedIntrinsicGasForAlternativeFeeCurrency + - INTRINSIC_TX_GAS_COST - - savingGasStableTokenTransferPaidWithSameStable, - transferToken: StableToken.cUSD, - feeToken: StableToken.cUSD, - }) - }) - }) - }) - } - }) - - describe('Transfer with Demurrage >', () => { - for (const syncMode of syncModes) { - describe(`${syncMode} Node >`, () => { - let inflationManager: InflationManager - before(`start geth on sync: ${syncMode}`, async () => { - await restartWithCleanNodes() - inflationManager = new InflationManager( - 'http://localhost:8545', - validatorAddress, - StableToken.cUSD - ) - await startSyncNode(syncMode) - }) - - describe('when there is demurrage of 50% applied', () => { - describe('when setting a gas amount greater than the amount of gas necessary', () => { - let balances: BalanceWatcher - let expectedFees: Fees - let txRes: TestTxResults - - before(async () => { - balances = await newBalanceWatcher(kit, [ - FromAddress, - ToAddress, - gatewayFeeRecipientAddress, - governanceAddress, - ]) - - await inflationManager.setInflationRateForNextTransfer(new BigNumber(2)) - const feeCurrency = await kit.celoTokens.getFeeCurrencyAddress(StableToken.cUSD) - txRes = await runTestTransaction( - await transferCeloGold(FromAddress, ToAddress, TransferAmount, { - feeCurrency, - }), - INTRINSIC_TX_GAS_COST + ADDITIONAL_INTRINSIC_TX_GAS_COST, - feeCurrency - ) - - await balances.update() - expectedFees = txRes.fees - }) - - it('should succeed', () => assert.isTrue(txRes.ok)) - - it('should use the expected amount of gas', () => - assert.equal(txRes.gas.used, txRes.gas.expected)) - - it("should decrement the sender's Celo Gold balance by the transfer amount", () => { - assertEqualBN(balances.delta(FromAddress, Token.CELO).negated(), TransferAmount) - }) - - it("should increment the receiver's Celo Gold balance by the transfer amount", () => { - assertEqualBN(balances.delta(ToAddress, Token.CELO), TransferAmount) - }) - - it("should halve the sender's Celo Dollar balance due to demurrage and decrement it by the total fees", () => { - assertEqualBN( - balances - .initial(FromAddress, StableToken.cUSD) - .idiv(2) - .minus(balances.current(FromAddress, StableToken.cUSD)), - expectedFees.total - ) - }) - - it("should halve the gateway fee recipient's Celo Dollar balance then increase it by the gateway fee", () => { - assertEqualBN( - balances - .current(gatewayFeeRecipientAddress, StableToken.cUSD) - .minus(balances.initial(gatewayFeeRecipientAddress, StableToken.cUSD).idiv(2)), - expectedFees.gateway - ) - }) - - it("should halve the infrastructure fund's Celo Dollar balance then increment it by the base portion of the gas fees", () => { - assertEqualBN( - balances - .current(governanceAddress, StableToken.cUSD) - .minus(balances.initial(governanceAddress, StableToken.cUSD).idiv(2)), - expectedFees.base - ) - }) - }) - }) - }) - } - }) -}) diff --git a/packages/celotool/src/e2e-tests/utils.ts b/packages/celotool/src/e2e-tests/utils.ts deleted file mode 100644 index 6c6aff2d3..000000000 --- a/packages/celotool/src/e2e-tests/utils.ts +++ /dev/null @@ -1,408 +0,0 @@ -/* tslint:disable: no-console */ -import BigNumber from 'bignumber.js' -import { assert } from 'chai' -import fs from 'fs' -import { join as joinPath, resolve as resolvePath } from 'path' -import readLastLines from 'read-last-lines' -import Web3 from 'web3' -import { spawnCmd, spawnCmdWithExitOnFailure } from '../lib/cmd-utils' -import { envVar, fetchEnvOrFallback } from '../lib/env-utils' -import { - AccountType, - getPrivateKeysFor, - getValidatorsInformation, - privateKeyToAddress, - privateKeyToPublicKey, -} from '../lib/generate_utils' -import { - buildGeth, - buildGethAll, - checkoutGethRepo, - connectPeers, - connectValidatorPeers, - getEnodeAddress, - getLogFilename, - initAndStartGeth, - initGeth, - migrateContracts, - resetDataDir, - restoreDatadir, - snapshotDatadir, - startGeth, - writeGenesis, - writeGenesisWithMigrations, -} from '../lib/geth' -import { GethInstanceConfig } from '../lib/interfaces/geth-instance-config' -import { GethRepository } from '../lib/interfaces/geth-repository' -import { GethRunConfig } from '../lib/interfaces/geth-run-config' -import { stringToBoolean } from '../lib/utils' - -const MonorepoRoot = resolvePath(joinPath(__dirname, '../..', '../..')) -const verboseOutput = false -// The mnemonic used for the e2e tests -export const mnemonic = - 'jazz ripple brown cloth door bridge pen danger deer thumb cable prepare negative library vast' - -export async function initAndSyncGethWithRetry( - gethConfig: GethRunConfig, - gethBinaryPath: string, - instance: GethInstanceConfig, - connectInstances: GethInstanceConfig[], - verbose: boolean, - retries: number -) { - for (let i = 1; i <= retries; i++) { - try { - await initAndStartGeth(gethConfig, gethBinaryPath, instance, verbose) - await connectPeers(connectInstances, verbose) - await waitToFinishInstanceSyncing(instance) - break - } catch (error) { - console.info(`initAndSyncGethWithRetry error: ${error}`) - const logFilename = getLogFilename(gethConfig.runPath, instance) - console.info(`tail -50 ${logFilename}`) - console.info(await readLastLines.read(logFilename, 50)) - if (i === retries) { - throw error - } else { - console.info(`Retrying ${i}/${retries} ...`) - await killInstance(instance) - continue - } - } - } - return instance -} - -export async function waitToFinishInstanceSyncing(instance: GethInstanceConfig) { - const { wsport, rpcport } = instance - console.info(`${instance.name}: syncing start`) - await waitToFinishSyncing(new Web3(`${rpcport ? 'http' : 'ws'}://localhost:${rpcport || wsport}`)) - console.info(`${instance.name}: syncing finished`) -} - -export async function waitToFinishSyncing(web3: any) { - while ((await web3.eth.isSyncing()) || (await web3.eth.getBlockNumber()) === 0) { - await sleep(0.1) - } -} - -export async function waitForBlock(web3: Web3, blockNumber: number) { - // const epoch = new BigNumber(await validators.methods.getEpochSize().call()).toNumber() - let currentBlock: number - do { - currentBlock = await web3.eth.getBlockNumber() - await sleep(0.1) - } while (currentBlock < blockNumber) -} - -export async function waitForEpochTransition(web3: Web3, epoch: number) { - // const epoch = new BigNumber(await validators.methods.getEpochSize().call()).toNumber() - let blockNumber: number - do { - blockNumber = await web3.eth.getBlockNumber() - await sleep(0.1) - } while (blockNumber % epoch !== 1) -} - -export async function waitForAnnounceToStabilize(web3: Web3) { - // Due to a problem in the announce protocol's settings, it can take a minute for all the validators - // to be aware of each other even though they are connected. This can lead to the first validator missing - // block signatures initially. So we wait for that to pass. - // Before we used mycelo, this wasn't noticeable because the migrations meant that the network would have - // been running for close to 10 minutes already, which was more than enough time. - // TODO: This function and its uses can be removed after the announce startup behavior has been resolved. - await waitForBlock(web3, 70) -} - -export function assertAlmostEqual( - actual: BigNumber, - expected: BigNumber, - delta: BigNumber = new BigNumber(10).pow(12).times(5) -) { - if (expected.isZero()) { - assert.equal(actual.toFixed(), expected.toFixed()) - } else { - const isCloseTo = actual.minus(expected).abs().lte(delta) - assert( - isCloseTo, - `expected ${actual.toString()} to almost equal ${expected.toString()} +/- ${delta.toString()}` - ) - } -} - -type Signal = 'TERM' | 'KILL' | 'INT' | 'STOP' | 'CONT' - -export async function signalProcess(identifier: string | number, signal: Signal): Promise { - const result = - typeof identifier === 'number' - ? await spawnCmd('kill', ['-s', signal, identifier.toString()], { silent: true }) - : await spawnCmd('pkill', [`-SIG${signal}`, identifier], { silent: true }) - - if (result !== 0) { - console.warn(`Attempt to send signal ${signal} to ${identifier} exited with code ${result}`) - } -} - -export async function processIsRunning(identifier: string | number): Promise { - if (typeof identifier === 'number') { - return (await spawnCmd('kill', ['-0', identifier.toString()], { silent: true })) === 0 - } else { - return (await spawnCmd('pgrep', [identifier], { silent: true })) === 0 - } -} - -export async function killGeth() { - console.info(`Killing ALL geth instances`) - await shutdownOrKill('geth') -} - -export async function killInstance(instance: GethInstanceConfig) { - if (instance.pid) { - await signalProcess(instance.pid, 'KILL') - } -} - -export async function shutdownOrKill(identifier: string | number, signal: Signal = 'INT') { - await signalProcess(identifier, signal) - - // Poll for remaining processes for up to ~30s with exponential backoff. - let processRemaining = true - for (let i = 0; i < 10 && processRemaining; i++) { - await sleep(0.03 * Math.pow(2, i)) - processRemaining = await processIsRunning(identifier) - } - - if (processRemaining) { - console.warn('shutdownOrKill: clean shutdown failed') - await signalProcess(identifier, 'KILL') - } - - // Sleep an additional 3 seconds to give time for the ports to be free. - await sleep(3.0) -} - -export function sleep(seconds: number, verbose = false) { - if (verbose) { - console.log(`Sleeping for ${seconds} seconds. Stay tuned!`) - } - return new Promise((resolve) => setTimeout(resolve, seconds * 1000)) -} - -export async function assertRevert(promise: any, errorMessage: string = ''): Promise { - try { - await promise - assert.fail('Expected revert not received') - } catch (error: any) { - const revertFound = error.message.search('revert') >= 0 - if (errorMessage === '') { - assert(revertFound, `Expected "revert", got ${error} instead`) - } else { - assert(revertFound, errorMessage) - } - } -} - -function gethRepositoryFromFlags() { - const argv = require('minimist')(process.argv.slice(2)) - return { - path: argv.localgeth || '/tmp/geth', - remote: !argv.localgeth, - branch: argv.branch, - } -} - -export function getHooks(gethConfig: GethRunConfig) { - return getContext(gethConfig, true).hooks -} - -export function getContext(gethConfig: GethRunConfig, verbose: boolean = verboseOutput) { - // Use of mycelo can be enabled through gethConfig or through an env variable - const useMycelo = - !!gethConfig.useMycelo || - stringToBoolean(fetchEnvOrFallback(envVar.E2E_TESTS_FORCE_USE_MYCELO, 'false')) - const validatorInstances = gethConfig.instances.filter((x: any) => x.validating) - - const numValidators = validatorInstances.length - - const validatorPrivateKeys = getPrivateKeysFor(AccountType.VALIDATOR, mnemonic, numValidators) - const attestationKeys = getPrivateKeysFor(AccountType.ATTESTATION, mnemonic, numValidators) - const validators = getValidatorsInformation(mnemonic, numValidators) - - const proxyInstances = gethConfig.instances.filter((x: any) => x.isProxy) - const numProxies = proxyInstances.length - - const proxyNodeKeys = getPrivateKeysFor(AccountType.PROXY, mnemonic, numProxies) - const proxyEnodes = proxyNodeKeys.map((x: string, i: number) => [ - proxyInstances[i].name, - getEnodeAddress(privateKeyToPublicKey(x), '127.0.0.1', proxyInstances[i].proxyport!), - getEnodeAddress(privateKeyToPublicKey(x), '127.0.0.1', proxyInstances[i].port), - ]) - - const repo: GethRepository = gethConfig.repository || gethRepositoryFromFlags() - const gethBinaryPath = `${repo.path}/build/bin/geth` - const initialize = async () => { - if (repo.remote) { - await checkoutGethRepo(repo.branch || 'master', repo.path) - } - - if (useMycelo) { - await buildGethAll(repo.path) - } else { - await buildGeth(repo.path) - } - - if (!gethConfig.keepData && fs.existsSync(gethConfig.runPath)) { - await resetDataDir(gethConfig.runPath, verbose) - } - - if (!fs.existsSync(gethConfig.runPath)) { - // @ts-ignore - fs.mkdirSync(gethConfig.runPath, { recursive: true }) - } - - if (useMycelo) { - // Compile the contracts first because mycelo assumes they are compiled already, unless told not to - if (!gethConfig.myceloSkipCompilingContracts) { - await spawnCmdWithExitOnFailure('yarn', ['truffle', 'compile'], { - cwd: `${MonorepoRoot}/packages/protocol`, - }) - } - await writeGenesisWithMigrations(gethConfig, repo.path, mnemonic, validators.length, verbose) - } else { - await writeGenesis(gethConfig, validators, verbose) - } - - let validatorIndex = 0 - let proxyIndex = 0 - - for (const instance of gethConfig.instances) { - if (instance.isProxied) { - // Proxied validators should connect to only the proxy - // Find this proxied validator's proxy - const proxyEnode = proxyEnodes.filter((x: any) => x[0] === instance.proxy) - - if (proxyEnode.length !== 1) { - throw new Error('proxied validator must have exactly one proxy') - } - - instance.proxies = [proxyEnode[0][1]!, proxyEnode[0][2]!] - } - - // Set the private key for the validator or proxy instance - if (instance.validating) { - instance.privateKey = instance.privateKey || validatorPrivateKeys[validatorIndex] - validatorIndex++ - } else if (instance.isProxy) { - instance.nodekey = instance.privateKey || proxyNodeKeys[proxyIndex] - proxyIndex++ - } - - if (!instance.minerValidator && (instance.validating || instance.isProxied)) { - instance.minerValidator = privateKeyToAddress(instance.privateKey!) - } - } - - // The proxies will need to know their proxied validator's address - for (const instance of gethConfig.instances) { - if (instance.isProxy) { - const proxiedValidator = gethConfig.instances.filter( - (x: GethInstanceConfig) => x.proxy === instance.name - ) - - if (proxiedValidator.length !== 1) { - throw new Error('proxied validator must have exactly one proxy') - } - - instance.proxiedValidatorAddress = privateKeyToAddress(proxiedValidator[0].privateKey!) - } - } - - if (useMycelo || !(gethConfig.migrate || gethConfig.migrateTo)) { - // Just need to initialize the nodes in this case. No need to actually start the network - // since we don't need to run the migrations against it. - for (const instance of gethConfig.instances) { - await initGeth(gethConfig, gethBinaryPath, instance, verbose) - } - return - } - - // Start all the instances - for (const instance of gethConfig.instances) { - await initAndStartGeth(gethConfig, gethBinaryPath, instance, verbose) - } - - // Directly connect validator peers that are not using a bootnode or proxy. - await connectValidatorPeers(gethConfig.instances) - - await Promise.all( - gethConfig.instances.filter((i) => i.validating).map((i) => waitToFinishInstanceSyncing(i)) - ) - - await migrateContracts( - MonorepoRoot, - validatorPrivateKeys, - attestationKeys, - validators.map((x) => x.address), - gethConfig.migrateTo, - gethConfig.migrationOverrides - ) - } - - const before = async () => { - await initialize() - - await killGeth() - - // Snapshot the datadir after the contract migrations so we can start from a "clean slate" - // for every test. - for (const instance of gethConfig.instances) { - await snapshotDatadir(gethConfig.runPath, instance, verbose) - } - } - - const restart = async () => { - await killGeth() - - // just in case - gethConfig.keepData = true - - let validatorIndex = 0 - const validatorIndices: number[] = [] - - for (const instance of gethConfig.instances) { - validatorIndices.push(validatorIndex) - if (instance.validating) { - validatorIndex++ - } - } - - // restore data dirs - await Promise.all( - gethConfig.instances.map((instance) => restoreDatadir(gethConfig.runPath, instance)) - ) - - // do in sequence, not concurrently to avoid flaky errors - for (let i = 0; i < gethConfig.instances.length; i++) { - const instance = gethConfig.instances[i] - if (!instance.privateKey && instance.validating) { - instance.privateKey = validatorPrivateKeys[validatorIndices[i]] - } - - if (!instance.minerValidator && (instance.validating || instance.isProxied)) { - instance.minerValidator = privateKeyToAddress(instance.privateKey!) - } - - await startGeth(gethConfig, gethBinaryPath, instance, verbose) - } - - await connectValidatorPeers(gethConfig.instances) - } - - const after = () => killGeth() - - return { - validators, - hooks: { initialize, before, after, restart, gethBinaryPath }, - } -} diff --git a/packages/celotool/src/e2e-tests/validator_order_tests.ts b/packages/celotool/src/e2e-tests/validator_order_tests.ts deleted file mode 100644 index 2f8b16ec3..000000000 --- a/packages/celotool/src/e2e-tests/validator_order_tests.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { assert } from 'chai' -import _ from 'lodash' -import Web3 from 'web3' -import { GethRunConfig } from '../lib/interfaces/geth-run-config' -import { getContext, sleep } from './utils' - -const VALIDATORS = 5 -const EPOCH = 20 -const EPOCHS_TO_WAIT = 3 -const BLOCK_COUNT = EPOCH * EPOCHS_TO_WAIT - -const TMP_PATH = '/tmp/e2e' - -describe('governance tests', () => { - const gethConfig: GethRunConfig = { - networkId: 1101, - network: 'local', - runPath: TMP_PATH, - migrate: true, - instances: _.range(VALIDATORS).map((i) => ({ - name: `validator${i}`, - validating: true, - syncmode: 'full', - port: 30303 + 2 * i, - rpcport: 8545 + 2 * i, - })), - genesisConfig: { - epoch: EPOCH, - churritoBlock: 0, - donutBlock: 0, - espressoBlock: 0, - }, - } - - const context: any = getContext(gethConfig) - let web3: Web3 - - before(async function (this: any) { - this.timeout(0) - await context.hooks.before() - }) - - after(async function (this: any) { - this.timeout(0) - await context.hooks.after() - }) - - describe('Validator ordering', () => { - before(async function () { - this.timeout(0) - web3 = new Web3('http://localhost:8545') - await context.hooks.restart() - }) - - it('properly orders validators randomly', async function (this: any) { - this.timeout(320000 /* 320 seconds */) - // If a consensus round fails during this test, the results are inconclusive. - // Retry up to two times to mitigate this issue. Restarting the nodes is not needed. - this.retries(2) - - const latestBlockNumber = (await web3.eth.getBlock('latest')).number - const indexInEpoch = ((latestBlockNumber % EPOCH) + EPOCH - 1) % EPOCH - const nextEpoch = latestBlockNumber + (EPOCH - indexInEpoch) - - // Wait for enough blocks. - while ((await web3.eth.getBlock('latest')).number < nextEpoch + BLOCK_COUNT) { - await sleep(2) - } - - // Fetch the validator for each block. - const blocks = await Promise.all( - _.range(BLOCK_COUNT).map(async (i) => web3.eth.getBlock(i + nextEpoch)) - ) - const validators = blocks.map((block) => block.miner) - - // Ensure each validator has an equal number of blocks. - const expectedCount = BLOCK_COUNT / VALIDATORS - for (const [validator, count] of Object.entries(_.countBy(validators))) { - assert.equal(count, expectedCount, `${validator} should have mined ${expectedCount} blocks`) - } - - const orderings: string[][] = [] - for (let i = 0; i < EPOCHS_TO_WAIT; i++) { - const epochValidators = validators.slice(i * EPOCH, (i + 1) * EPOCH) - const ordering = epochValidators.slice(0, VALIDATORS) - - // Ensure within an epoch, ordering is consistent. - for (const [index, validator] of ordering.entries()) { - assert.equal(validator, epochValidators[VALIDATORS + index]) - } - - // Ensure each epoch has a unique ordering. - // Note: This has a 1/(VALIDATORS!) chance of failing. With 10 validators, this is negligible. - for (const prevOrdering of orderings) { - assert(!_.isEqual(prevOrdering, ordering), 'ordering is not unique') - } - orderings.push(ordering) - } - }) - }) -}) diff --git a/packages/celotool/src/lib/artifacts.ts b/packages/celotool/src/lib/artifacts.ts deleted file mode 100644 index f4cf6e475..000000000 --- a/packages/celotool/src/lib/artifacts.ts +++ /dev/null @@ -1,111 +0,0 @@ -/* tslint:disable: no-console */ -import { existsSync, mkdirSync, readFileSync, writeFile } from 'fs' -import { promisify } from 'util' -import { execCmd } from './cmd-utils' -import { doCheckOrPromptIfStagingOrProduction, envVar, fetchEnv, isProduction } from './env-utils' - -export const CONTRACTS_TO_COPY = [ - 'Attestations', - 'Escrow', - 'Exchange', - 'GoldToken', - 'Registry', - 'Reserve', - 'StableToken', -] - -export async function downloadArtifacts(celoEnv: string) { - let baseCmd = `yarn --cwd ../protocol run download-artifacts -n ${celoEnv}` - console.log(`Downloading artifacts for ${celoEnv}`) - if (isProduction()) { - baseCmd += ` -b contract_artifacts_production` - } - try { - await execCmd(baseCmd) - } catch (error) { - console.error(`Unable to download artifacts for ${celoEnv}`) - console.error(error) - process.exit(1) - } -} - -export async function uploadArtifacts(celoEnv: string, checkOrPromptIfStagingOrProduction = true) { - if (checkOrPromptIfStagingOrProduction) { - await doCheckOrPromptIfStagingOrProduction() - } - - let baseCmd = `yarn --cwd ../protocol run upload-artifacts -n ${celoEnv}` - if (isProduction()) { - baseCmd += ` -b contract_artifacts_production` - } - console.log(`Uploading artifacts for ${celoEnv}`) - try { - await execCmd(baseCmd) - } catch (error) { - console.error(`Unable to upload artifacts for ${celoEnv}`) - console.error(error) - process.exit(1) - } -} - -function getContract(fileData: string) { - const json = JSON.parse(fileData) - return { - abi: json.abi, - contractName: json.contractName, - schemaVersion: json.schemaVersion, - updatedAt: json.updatedAt, - } -} - -const toFile = promisify(writeFile) - -export async function copyContractArtifacts( - celoEnv: string, - outputPath: string, - contractList: string[] -) { - const baseContractPath = `../protocol/build/${celoEnv}/contracts` - - if (!existsSync(outputPath)) { - mkdirSync(outputPath) - } - - await Promise.all( - contractList.map(async (contract) => { - const json = getContract(readFileSync(`${baseContractPath}/${contract}.json`).toString()) - - const proxyJson = JSON.parse( - readFileSync(`${baseContractPath}/${contract}Proxy.json`).toString() - ) - const address = proxyJson.networks[fetchEnv(envVar.NETWORK_ID)].address - - await toFile( - `${outputPath}/${contract}.ts`, - `import Web3 from 'web3'\n\n` + - `export default async function getInstance(web3: Web3) {\n` + - ` return new web3.eth.Contract(\n` + - ` ${JSON.stringify(json.abi, null, 2)},\n` + - ` "${address}"\n` + - ` )\n` + - `}` - ) - }) - ) -} - -export async function getContractAddresses(celoEnv: string, contractList: string[]) { - const baseContractPath = `../protocol/build/${celoEnv}/contracts` - - const contracts: Record = {} - - for (const contract of contractList) { - const proxyJson = JSON.parse( - readFileSync(`${baseContractPath}/${contract}Proxy.json`).toString() - ) - const address = proxyJson.networks[fetchEnv(envVar.NETWORK_ID)].address - contracts[contract] = address - } - - return contracts -} diff --git a/packages/celotool/src/lib/azure.ts b/packages/celotool/src/lib/azure.ts deleted file mode 100644 index e1addeed9..000000000 --- a/packages/celotool/src/lib/azure.ts +++ /dev/null @@ -1,314 +0,0 @@ -import sleep from 'sleep-promise' -import { execCmdWithExitOnFailure } from 'src/lib/cmd-utils' -import { retryCmd } from 'src/lib/utils' -import { getAksClusterConfig } from './context-utils' -import { AksClusterConfig } from './k8s-cluster/aks' - -/** - * getIdentity gets basic info on an existing identity. If the identity doesn't - * exist, undefined is returned - */ -export async function getIdentity(clusterConfig: AksClusterConfig, identityName: string) { - const [matchingIdentitiesStr] = await execCmdWithExitOnFailure( - `az identity list -g ${clusterConfig.resourceGroup} --query "[?name == '${identityName}']" -o json` - ) - const matchingIdentities = JSON.parse(matchingIdentitiesStr) - if (!matchingIdentities.length) { - return - } - // There should only be one exact match by name - return matchingIdentities[0] -} - -// createIdentityIdempotent creates an identity if it doesn't already exist. -// Returns an object including basic info on the identity. -export async function createIdentityIdempotent( - clusterConfig: AksClusterConfig, - identityName: string -) { - const identity = await getIdentity(clusterConfig, identityName) - if (identity) { - console.info( - `Skipping identity creation, ${identityName} in resource group ${clusterConfig.resourceGroup} already exists` - ) - return identity - } - console.info(`Creating identity ${identityName} in resource group ${clusterConfig.resourceGroup}`) - // This command is idempotent-- if the identity exists, the existing one is given - const [results] = await execCmdWithExitOnFailure( - `az identity create -n ${identityName} -g ${clusterConfig.resourceGroup} -o json` - ) - return JSON.parse(results) -} - -/** - * deleteIdentity gets basic info on an existing identity - */ -export function deleteIdentity(clusterConfig: AksClusterConfig, identityName: string) { - return execCmdWithExitOnFailure( - `az identity delete -n ${identityName} -g ${clusterConfig.resourceGroup} -o json` - ) -} - -async function roleIsAssigned(assignee: string, scope: string, role: string) { - const [matchingAssignedRoles] = await retryCmd( - () => - execCmdWithExitOnFailure( - `az role assignment list --assignee ${assignee} --scope ${scope} --query "length([?roleDefinitionName == '${role}'])" -o tsv` - ), - 10 - ) - return parseInt(matchingAssignedRoles.trim(), 10) > 0 -} - -export async function assignRoleIdempotent( - assigneeObjectId: string, - assigneePrincipalType: string, - scope: string, - role: string -) { - if (await roleIsAssigned(assigneeObjectId, scope, role)) { - console.info( - `Skipping role assignment, role ${role} already assigned to ${assigneeObjectId} for scope ${scope}` - ) - return - } - console.info( - `Assigning role ${role} to ${assigneeObjectId} type ${assigneePrincipalType} for scope ${scope}` - ) - await retryCmd( - () => - execCmdWithExitOnFailure( - `az role assignment create --role "${role}" --assignee-object-id ${assigneeObjectId} --assignee-principal-type ${assigneePrincipalType} --scope ${scope}` - ), - 10 - ) -} - -export async function getAKSNodeResourceGroup(clusterConfig: AksClusterConfig) { - const [nodeResourceGroup] = await execCmdWithExitOnFailure( - `az aks show --name ${clusterConfig.clusterName} --resource-group ${clusterConfig.resourceGroup} --query nodeResourceGroup -o tsv` - ) - return nodeResourceGroup.trim() -} - -/** - * Gets the AKS Service Principal Object ID if one exists. Otherwise, an empty string is given. - */ -export async function getAKSServicePrincipalObjectId(clusterConfig: AksClusterConfig) { - // Get the correct object ID depending on the cluster configuration - // See https://github.com/Azure/aad-pod-identity/blob/b547ba86ab9b16d238db8a714aaec59a046afdc5/docs/readmes/README.role-assignment.md#obtaining-the-id-of-the-managed-identity--service-principal - const [rawServicePrincipalClientId] = await execCmdWithExitOnFailure( - `az aks show -n ${clusterConfig.clusterName} --query servicePrincipalProfile.clientId -g ${clusterConfig.resourceGroup} -o tsv` - ) - const servicePrincipalClientId = rawServicePrincipalClientId.trim() - // This will be the value of the service principal client ID if a managed service identity - // is being used instead of a service principal. - if (servicePrincipalClientId === 'msi') { - return '' - } - const [rawObjectId] = await execCmdWithExitOnFailure( - `az ad sp show --id ${servicePrincipalClientId} --query id -o tsv` - ) - return rawObjectId.trim() -} - -/** - * If an AKS cluster is using a managed service identity, the objectId is returned. - * Otherwise, an empty string is given. - */ -export async function getAKSManagedServiceIdentityObjectId(clusterConfig: AksClusterConfig) { - const [managedIdentityObjectId] = await execCmdWithExitOnFailure( - `az aks show -n ${clusterConfig.clusterName} --query identityProfile.kubeletidentity.objectId -g ${clusterConfig.resourceGroup} -o tsv` - ) - return managedIdentityObjectId.trim() -} - -export async function registerStaticIPIfNotRegistered(name: string, resourceGroupIP: string) { - // This returns an array of matching IP addresses. If there is no matching IP - // address, an empty array is returned. We expect at most 1 matching IP - const [existingIpsStr] = await execCmdWithExitOnFailure( - `az network public-ip list --resource-group ${resourceGroupIP} --query "[?name == '${name}' && sku.name == 'Standard'].ipAddress" -o json` - ) - const existingIps = JSON.parse(existingIpsStr) - if (existingIps.length) { - console.info(`Skipping IP address registration, ${name} on ${resourceGroupIP} exists`) - // We expect only 1 matching IP - return existingIps[0] - } - console.info(`Registering IP address ${name} on ${resourceGroupIP}`) - const [address] = await execCmdWithExitOnFailure( - `az network public-ip create --resource-group ${resourceGroupIP} --name ${name} --allocation-method Static --sku Standard --query publicIp.ipAddress -o tsv` - ) - return address.trim() -} - -export async function deallocateStaticIP(name: string, resourceGroupIP: string) { - console.info(`Deallocating IP address ${name} on ${resourceGroupIP}`) - return execCmdWithExitOnFailure( - `az network public-ip delete --resource-group ${resourceGroupIP} --name ${name}` - ) -} - -export async function waitForStaticIPDetachment(name: string, resourceGroup: string) { - const maxTryCount = 15 - const tryIntervalMs = 3000 - for (let tryCount = 0; tryCount < maxTryCount; tryCount++) { - const [allocated] = await execCmdWithExitOnFailure( - `az network public-ip show --resource-group ${resourceGroup} --name ${name} --query ipConfiguration.id -o tsv` - ) - if (allocated.trim() === '') { - return true - } - await sleep(tryIntervalMs) - } - throw Error(`Too many tries waiting for static IP association ID removal`) -} - -/** - * This creates an Azure identity to access a key vault - */ -export async function createKeyVaultIdentityIfNotExists( - context: string, - identityName: string, - keyVaultName: string, - keyVaultResourceGroup: string | null | undefined, - keyPermissions: string[] | null, - secretPermissions: string[] | null -) { - const clusterConfig = getAksClusterConfig(context) - const identity = await createIdentityIdempotent(clusterConfig, identityName) - // We want to grant the identity for the cluster permission to manage the odis signer identity. - // Get the correct object ID depending on the cluster configuration, either - // the service principal or the managed service identity. - // See https://github.com/Azure/aad-pod-identity/blob/b547ba86ab9b16d238db8a714aaec59a046afdc5/docs/readmes/README.role-assignment.md#obtaining-the-id-of-the-managed-identity--service-principal - let assigneeObjectId = await getAKSServicePrincipalObjectId(clusterConfig) - let assigneePrincipalType = 'ServicePrincipal' - // TODO Check how to manage the MSI type - if (!assigneeObjectId) { - assigneeObjectId = await getAKSManagedServiceIdentityObjectId(clusterConfig) - // assigneePrincipalType = 'MSI' - assigneePrincipalType = 'ServicePrincipal' - } - await assignRoleIdempotent( - assigneeObjectId, - assigneePrincipalType, - identity.id, - 'Managed Identity Operator' - ) - // Allow the odis signer identity to access the correct key vault - await setKeyVaultPolicyIfNotSet( - clusterConfig, - keyVaultName, - keyVaultResourceGroup, - identity, - keyPermissions, - secretPermissions - ) - return identity -} - -async function setKeyVaultPolicyIfNotSet( - clusterConfig: AksClusterConfig, - keyVaultName: string, - keyVaultResourceGroup: string | null | undefined, - azureIdentity: any, - keyPermissions: string[] | null, - secretPermissions: string[] | null -) { - const kvResourceGroup = keyVaultResourceGroup - ? keyVaultResourceGroup - : clusterConfig.resourceGroup - - const queryFilters = [`?objectId == '${azureIdentity.principalId}'`] - if (keyPermissions) { - queryFilters.push( - `sort(permissions.keys) == [${keyPermissions.map((perm) => `'${perm}'`).join(', ')}]` - ) - } - if (secretPermissions) { - queryFilters.push( - `sort(permissions.secrets) == [${secretPermissions.map((perm) => `'${perm}'`).join(', ')}]` - ) - } - - const [keyVaultPoliciesStr] = await execCmdWithExitOnFailure( - `az keyvault show --name ${keyVaultName} -g ${kvResourceGroup} --query "properties.accessPolicies[${queryFilters.join( - ' && ' - )}]"` - ) - const keyVaultPolicies = JSON.parse(keyVaultPoliciesStr) - if (keyVaultPolicies.length) { - const keyPermStr = keyPermissions ? `key permissions: ${keyPermissions.join(' ')}` : '' - const secretPermStr = secretPermissions - ? `secret permissions: ${secretPermissions.join(' ')}` - : '' - console.info( - `Skipping setting policy {${keyPermStr}, ${secretPermStr}}. Already set for vault ${keyVaultName} and identity objectId ${azureIdentity.principalId}` - ) - return - } - - if (keyPermissions) { - console.info( - `Setting key permissions ${keyPermissions.join( - ' ' - )} for vault ${keyVaultName} and identity objectId ${azureIdentity.principalId}` - ) - return execCmdWithExitOnFailure( - `az keyvault set-policy --name ${keyVaultName} --key-permissions ${keyPermissions.join( - ' ' - )} --object-id ${azureIdentity.principalId} -g ${kvResourceGroup}` - ) - } - - if (secretPermissions) { - console.info( - `Setting secret permissions ${secretPermissions.join( - ' ' - )} for vault ${keyVaultName} and identity objectId ${azureIdentity.principalId}` - ) - return execCmdWithExitOnFailure( - `az keyvault set-policy --name ${keyVaultName} --secret-permissions ${secretPermissions.join( - ' ' - )} --object-id ${azureIdentity.principalId} -g ${kvResourceGroup}` - ) - } -} - -/** - * deleteAzureKeyVaultIdentity deletes the key vault policy and the managed identity - */ -export async function deleteAzureKeyVaultIdentity( - context: string, - identityName: string, - keyVaultName: string -) { - const clusterConfig = getAksClusterConfig(context) - await deleteKeyVaultPolicy(clusterConfig, identityName, keyVaultName) - return deleteIdentity(clusterConfig, identityName) -} - -async function deleteKeyVaultPolicy( - clusterConfig: AksClusterConfig, - identityName: string, - keyVaultName: string -) { - const azureIdentity = await getIdentity(clusterConfig, identityName) - return execCmdWithExitOnFailure( - `az keyvault delete-policy --name ${keyVaultName} --object-id ${azureIdentity.principalId} -g ${clusterConfig.resourceGroup}` - ) -} - -/** - * @return the intended name of an azure identity given a key vault name - */ -export function getAzureKeyVaultIdentityName( - context: string, - prefix: string, - keyVaultName: string -) { - // from https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/resource-name-rules#microsoftmanagedidentity - const maxIdentityNameLength = 128 - return `${prefix}-${keyVaultName}-${context}`.substring(0, maxIdentityNameLength) -} diff --git a/packages/celotool/src/lib/blockchain.ts b/packages/celotool/src/lib/blockchain.ts deleted file mode 100644 index ee16f11f7..000000000 --- a/packages/celotool/src/lib/blockchain.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { getRandomTxNodeIP } from 'src/lib/kubernetes' -import Web3 from 'web3' - -export async function getWeb3Client(celoEnv: string) { - const transactionNodeIP = await getRandomTxNodeIP(celoEnv) - return new Web3(`ws://${transactionNodeIP}:8546`) -} diff --git a/packages/celotool/src/lib/celostats.ts b/packages/celotool/src/lib/celostats.ts deleted file mode 100644 index 8517ba5ff..000000000 --- a/packages/celotool/src/lib/celostats.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { - installGenericHelmChart, - removeGenericHelmChart, - upgradeGenericHelmChart, -} from 'src/lib/helm_deploy' -import { getBlockscoutUrl, getFornoUrl } from './endpoints' -import { envVar, fetchEnv, fetchEnvOrFallback } from './env-utils' -import { AccountType, getAddressesFor } from './generate_utils' - -const helmChartPath = '../helm-charts/celostats' - -export async function installHelmChart(celoEnv: string) { - return installGenericHelmChart({ - namespace: celoEnv, - releaseName: releaseName(celoEnv), - chartDir: helmChartPath, - parameters: helmParameters(celoEnv), - }) -} - -export async function removeHelmRelease(celoEnv: string) { - await removeGenericHelmChart(releaseName(celoEnv), celoEnv) -} - -export async function upgradeHelmChart(celoEnv: string) { - await upgradeGenericHelmChart({ - namespace: celoEnv, - releaseName: releaseName(celoEnv), - chartDir: helmChartPath, - parameters: helmParameters(celoEnv), - }) -} - -function helmParameters(celoEnv: string) { - return [ - `--set domain.name=${fetchEnv(envVar.CLUSTER_DOMAIN_NAME)}`, - `--set celostats.image.server.repository=${fetchEnv( - envVar.CELOSTATS_SERVER_DOCKER_IMAGE_REPOSITORY - )}`, - `--set celostats.image.server.tag=${fetchEnv(envVar.CELOSTATS_SERVER_DOCKER_IMAGE_TAG)}`, - `--set celostats.image.frontend.repository=${fetchEnv( - envVar.CELOSTATS_FRONTEND_DOCKER_IMAGE_REPOSITORY - )}`, - `--set celostats.image.frontend.tag=${fetchEnv(envVar.CELOSTATS_FRONTEND_DOCKER_IMAGE_TAG)}`, - `--set celostats.trusted_addresses='${String(generateAuthorizedAddresses()).replace( - /,/g, - '\\,' - )}'`, - `--set celostats.banned_addresses='${String( - fetchEnv(envVar.CELOSTATS_BANNED_ADDRESSES) - ).replace(/,/g, '\\,')}'`, - `--set celostats.reserved_addresses='${String( - fetchEnv(envVar.CELOSTATS_RESERVED_ADDRESSES) - ).replace(/,/g, '\\,')}'`, - `--set celostats.network_name='Celo ${celoEnv}'`, - `--set celostats.blockscout_url='${getBlockscoutUrl(celoEnv)}'`, - `--set celostats.jsonrpc='${getFornoUrl(celoEnv)}'`, - ] -} - -function releaseName(celoEnv: string) { - return `${celoEnv}-celostats` -} - -function generateAuthorizedAddresses() { - // TODO: Add the Proxy eth addresses when available - const mnemonic = fetchEnv(envVar.MNEMONIC) - const publicKeys = [] - const txNodes = parseInt(fetchEnv(envVar.TX_NODES), 0) - const validatorNodes = parseInt(fetchEnv(envVar.VALIDATORS), 0) - publicKeys.push(getAddressesFor(AccountType.TX_NODE, mnemonic, txNodes)) - publicKeys.push(getAddressesFor(AccountType.VALIDATOR, mnemonic, validatorNodes)) - - publicKeys.push(fetchEnvOrFallback(envVar.CELOSTATS_TRUSTED_ADDRESSES, '').split(',')) - return publicKeys.reduce((accumulator, value) => accumulator.concat(value), []).filter((_) => !!_) -} diff --git a/packages/celotool/src/lib/chaoskube.ts b/packages/celotool/src/lib/chaoskube.ts deleted file mode 100644 index f83e86890..000000000 --- a/packages/celotool/src/lib/chaoskube.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { makeHelmParameters } from 'src/lib/helm_deploy' -import { envVar, fetchEnv } from './env-utils' - -export function helmReleaseName(celoEnv: string) { - return celoEnv + '-chaoskube' -} - -export const helmChartDir = 'stable/chaoskube' - -export function helmParameters(celoEnv: string) { - return makeHelmParameters({ - interval: fetchEnv(envVar.CHAOS_TEST_KILL_INTERVAL), - labels: 'component=validators', - namespaces: celoEnv, - dryRun: 'false', - 'rbac.create': 'true', - 'rbac.serviceAccountName': `${celoEnv}-chaoskube`, - }) -} diff --git a/packages/celotool/src/lib/cloud-storage.ts b/packages/celotool/src/lib/cloud-storage.ts deleted file mode 100644 index 566b79de8..000000000 --- a/packages/celotool/src/lib/cloud-storage.ts +++ /dev/null @@ -1,81 +0,0 @@ -const { Storage } = require('@google-cloud/storage') - -const sleep = async (time: number) => { - return new Promise((resolve) => setTimeout(resolve, time)) -} - -export const createClient = (credentials?: any) => { - return new Storage({ credentials }) -} - -// Location ref: https://cloud.google.com/storage/docs/locations -// Storage classes ref: https://cloud.google.com/storage/docs/storage-classes -export const createBucket = async ( - client: any, - bucketName: string, - location: string = 'US-CENTRAL1', - storageClass: string = 'COLDLINE' -) => { - await client.createBucket(bucketName, { - location, - storageClass, - }) - await sleep(2000) -} - -export const createBucketIfNotExists = async ( - client: any, - bucketName: string, - location: string = 'US-CENTRAL1', - storageClass: string = 'COLDLINE' -) => { - if (!(await checkBucketExists(client, bucketName))) { - await createBucket(client, bucketName, location, storageClass) - } -} - -export const getBuckets = async (client: any) => { - const [buckets] = await client.getBuckets() - return buckets -} - -export const getFiles = async (client: any, bucketName: string) => { - const [files] = await client.bucket(bucketName).getFiles() - return files -} - -export const checkBucketExists = async (client: any, bucketName: string) => { - const buckets = await getBuckets(client) - return buckets.some((bucket: any) => bucket.name === bucketName) -} - -export const deleteBucket = async (client: any, bucketName: string) => { - await client.bucket(bucketName).delete() -} - -export const fileUpload = async ( - client: any, - bucketName: string, - srcFileName: string, - useCache: boolean = true -) => { - const uploadOptions = { - gzip: true, - metadata: { - cacheControl: useCache ? 'public, max-age=31536000' : 'no-cache', - }, - } - - await client.bucket(bucketName).upload(srcFileName, uploadOptions) -} - -export const fileDownload = async ( - client: any, - bucketName: string, - srcFileName: string, - dstFileName: string -) => { - await client.bucket(bucketName).file(srcFileName).download({ - destination: dstFileName, - }) -} diff --git a/packages/celotool/src/lib/cluster.ts b/packages/celotool/src/lib/cluster.ts deleted file mode 100644 index 95f6661cb..000000000 --- a/packages/celotool/src/lib/cluster.ts +++ /dev/null @@ -1,251 +0,0 @@ -import sleep from 'sleep-promise' -import { execCmd, execCmdWithExitOnFailure } from './cmd-utils' -import { getClusterConfigForContext, switchToContextCluster } from './context-utils' -import { doCheckOrPromptIfStagingOrProduction, envTypes, envVar, fetchEnv } from './env-utils' -import { - checkHelmVersion, - createAndUploadBackupSecretIfNotExists, - getServiceAccountName, - grantRoles, - installAndEnableMetricsDeps, - installCertManagerAndNginx, - installGCPSSDStorageClass, - isCelotoolHelmDryRun, - networkName, -} from './helm_deploy' -import { createServiceAccountIfNotExists } from './service-account-utils' -import { outputIncludes, switchToProjectFromEnv } from './utils' - -const SYSTEM_HELM_RELEASES = [ - 'nginx-ingress-release', - 'kube-lego-release', - 'cert-manager-cluster-issuers', -] -const HELM_RELEASE_REGEX = new RegExp(/(.*)-\d+\.\d+\.\d+$/) - -export async function switchToClusterFromEnv( - celoEnv: string, - checkOrPromptIfStagingOrProduction = true, - skipClusterSetup = true -) { - if (checkOrPromptIfStagingOrProduction) { - await doCheckOrPromptIfStagingOrProduction() - } - await checkHelmVersion() - - await switchToProjectFromEnv() - - if (!skipClusterSetup) { - if (!isCelotoolHelmDryRun()) { - // In this case we create the cluster if it does not exist - const createdCluster = await createClusterIfNotExists() - // Install common helm charts - await setupCluster(celoEnv, createdCluster) - } else { - console.info(`Skipping cluster setup due to --helmdryrun`) - } - } - - let currentCluster = null - try { - ;[currentCluster] = await execCmd('kubectl config current-context') - } catch (error) { - console.info('No cluster currently set') - } - - const projectName = fetchEnv(envVar.TESTNET_PROJECT_NAME) - const kubernetesClusterName = fetchEnv(envVar.KUBERNETES_CLUSTER_NAME) - const kubernetesClusterZone = fetchEnv(envVar.KUBERNETES_CLUSTER_ZONE) - - const expectedCluster = `gke_${projectName}_${kubernetesClusterZone}_${kubernetesClusterName}` - - if (currentCluster === null || currentCluster.trim() !== expectedCluster) { - await execCmdWithExitOnFailure( - `gcloud container clusters get-credentials ${kubernetesClusterName} --project ${projectName} --zone ${kubernetesClusterZone}` - ) - } - await execCmdWithExitOnFailure(`kubectl config set-context --current --namespace default`) -} - -export async function createClusterIfNotExists() { - const kubernetesClusterName = fetchEnv(envVar.KUBERNETES_CLUSTER_NAME) - const kubernetesClusterZone = fetchEnv(envVar.KUBERNETES_CLUSTER_ZONE) - await switchToProjectFromEnv() - const clusterExists = await outputIncludes( - `gcloud container clusters list --zone ${kubernetesClusterZone} --filter NAME=${kubernetesClusterName}`, - kubernetesClusterName, - `Cluster ${kubernetesClusterName} exists, skipping creation` - ) - - if (!clusterExists) { - const network = networkName(fetchEnv(envVar.CELOTOOL_CELOENV)) - console.info(`Creating cluster ${kubernetesClusterName} on network ${network}...`) - await execCmdWithExitOnFailure( - `gcloud container clusters create ${kubernetesClusterName} --zone ${kubernetesClusterZone} ${fetchEnv( - envVar.CLUSTER_CREATION_FLAGS - )} --network ${network}` - ) - return true - } - - return false -} - -export async function createNamespaceIfNotExists(namespace: string) { - const namespaceExists = await outputIncludes( - `kubectl get namespaces ${namespace} || true`, - namespace, - `Namespace ${namespace} exists, skipping creation` - ) - if (!namespaceExists) { - const cmd = `kubectl create namespace ${namespace} ${ - isCelotoolHelmDryRun() ? ' --dry-run=server' : '' - }` - await execCmdWithExitOnFailure(cmd) - } -} - -export async function setupCluster(celoEnv: string, createdCluster: boolean) { - const envType = fetchEnv(envVar.ENV_TYPE) - - await checkHelmVersion() - - await createNamespaceIfNotExists(celoEnv) - - const blockchainBackupServiceAccountName = getServiceAccountName('blockchain-backup-for') - console.info(`Service account for blockchain backup is \"${blockchainBackupServiceAccountName}\"`) - - await createServiceAccountIfNotExists(blockchainBackupServiceAccountName) - // This role is required for "compute.snapshots.get" permission - // Source: https://cloud.google.com/compute/docs/access/iam - await grantRoles(blockchainBackupServiceAccountName, 'roles/compute.storageAdmin') - // This role is required for "gcloud.container.clusters.get-credentials" permission - // This role is required for "container.clusters.get" permission - // Source: https://cloud.google.com/kubernetes-engine/docs/how-to/iam - await grantRoles(blockchainBackupServiceAccountName, 'roles/container.viewer') - - await createAndUploadBackupSecretIfNotExists(blockchainBackupServiceAccountName, celoEnv) - - // poll for cluster availability - if (createdCluster) { - await pollForRunningCluster() - } - - console.info('Deploying Tiller and Cert Manager Helm chart...') - - await installGCPSSDStorageClass() - - await installCertManagerAndNginx(celoEnv) - - if (envType !== envTypes.DEVELOPMENT) { - console.info('Installing metric tools installation') - await installAndEnableMetricsDeps(true) - } else { - console.info('Skipping metric tools installation for this development env') - } - - await setClusterLabels(celoEnv) -} - -export async function pollForRunningCluster() { - const kubernetesClusterName = fetchEnv(envVar.KUBERNETES_CLUSTER_NAME) - const kubernetesClusterZone = fetchEnv(envVar.KUBERNETES_CLUSTER_ZONE) - - await switchToProjectFromEnv() - - let attempts = 0 - while (attempts < 10) { - console.info('Waiting for cluster to be in status=RUNNING') - const [status] = await execCmdWithExitOnFailure( - `gcloud container clusters describe --zone ${kubernetesClusterZone} ${kubernetesClusterName} --format="value(status)"` - ) - if (status.trim() === 'RUNNING') { - return - } - attempts += 1 - await sleep(Math.pow(2, attempts) * 1000) - } - - console.error('Waited for too long for running cluster') - process.exit(1) -} - -export async function deleteCluster() { - const kubernetesClusterName = fetchEnv(envVar.KUBERNETES_CLUSTER_NAME) - const kubernetesClusterZone = fetchEnv(envVar.KUBERNETES_CLUSTER_ZONE) - - await switchToProjectFromEnv() - const clusterExists = await outputIncludes( - `gcloud container clusters list --zone ${kubernetesClusterZone} --filter NAME=${kubernetesClusterName}`, - kubernetesClusterName - ) - if (!clusterExists) { - console.error(`Cluster ${kubernetesClusterName} does not exist`) - process.exit(1) - } - - await execCmdWithExitOnFailure( - `gcloud container clusters delete ${kubernetesClusterName} --zone ${kubernetesClusterZone} --quiet` - ) -} - -export async function setClusterLabels(celoEnv: string) { - const envType = fetchEnv(envVar.ENV_TYPE) - const labelfn = async (key: string, value: string) => { - await execCmdWithExitOnFailure( - `gcloud container clusters update ${fetchEnv( - envVar.KUBERNETES_CLUSTER_NAME - )} --update-labels ${key}=${value} --zone ${fetchEnv(envVar.KUBERNETES_CLUSTER_ZONE)}` - ) - } - await labelfn('environment', envType) - await labelfn('envtype', envType === envTypes.PRODUCTION ? 'production' : 'nonproduction') - await labelfn('envinstance', celoEnv) -} - -export function getKubernetesClusterRegion(zone?: string): string { - if (!zone) { - zone = fetchEnv(envVar.KUBERNETES_CLUSTER_ZONE) - } - const matches = zone.match('^[a-z]+-[a-z]+[0-9]') - if (matches) { - return matches[0] - } else { - console.error('Unable to find kubernetes cluster region') - process.exit(1) - // Make the compiler happy - return '' - } -} -export interface HelmRelease { - Name: string - Chart: string - Status: string - Updated: string - Namespace: string -} - -export async function getNonSystemHelmReleases(): Promise { - const [json] = await execCmdWithExitOnFailure(`helm list -A --output json`) - const releases: HelmRelease[] = JSON.parse(json).Releases - return releases.filter((release) => !SYSTEM_HELM_RELEASES.includes(release.Name)) -} - -export function getPackageName(name: string) { - const prefix = HELM_RELEASE_REGEX.exec(name) - if (!prefix) { - return '' - } - - return prefix[1] === 'ethereum' ? 'testnet' : prefix[1] -} - -export async function switchToClusterFromEnvOrContext(argv: any, skipClusterSetup = false) { - if (argv.context === undefined) { - // GCP top level cluster. - await switchToClusterFromEnv(argv.celoEnv, true, skipClusterSetup) - } else { - await switchToContextCluster(argv.celoEnv, argv.context, skipClusterSetup) - return getClusterConfigForContext(argv.context) - } -} diff --git a/packages/celotool/src/lib/cmd-utils.ts b/packages/celotool/src/lib/cmd-utils.ts deleted file mode 100644 index 65a575c15..000000000 --- a/packages/celotool/src/lib/cmd-utils.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { exec, spawn, SpawnOptions } from 'child_process' - -export async function execCmdAndParseJson( - cmd: string, - execOptions: any = {}, - rejectWithOutput = false, - pipeOutput = false -) { - const [output] = await execCmd(cmd, execOptions, rejectWithOutput, pipeOutput) - return JSON.parse(output) -} - -// Returns a Promise which resolves to [stdout, stderr] array -export function execCmd( - cmd: string, - execOptions: any = {}, - rejectWithOutput = false, - pipeOutput = false -): Promise<[string, string]> { - return new Promise((resolve, reject) => { - if (process.env.CELOTOOL_VERBOSE === 'true') { - console.debug('$ ' + cmd) - pipeOutput = true - } - - exec(cmd, { maxBuffer: 1024 * 10000, ...execOptions }, (err, stdout, stderr) => { - if (pipeOutput) { - console.debug(stdout.toString()) - } - if (err || pipeOutput) { - console.error(stderr.toString()) - } - if (err) { - if (rejectWithOutput) { - reject([err, stdout.toString(), stderr.toString()]) - } else { - reject(err) - } - } else { - resolve([stdout.toString(), stderr.toString()]) - } - }) - }) -} - -export function spawnCmd( - cmd: string, - args: string[], - options?: SpawnOptions & { silent?: boolean } -) { - return new Promise(async (resolve, reject) => { - const { silent, ...spawnOptions } = options || { silent: false } - if (!silent) { - console.debug('$ ' + [cmd].concat(args).join(' ')) - } - const process = spawn(cmd, args, { ...spawnOptions, stdio: silent ? 'ignore' : 'inherit' }) - process.on('close', (code) => { - try { - resolve(code) - } catch (error) { - reject(error) - } - }) - }) -} - -// Returns a Promise which resolves to [stdout, stderr] array -export function execCmdWithExitOnFailure( - cmd: string, - options: any = {}, - pipeOutput = false -): Promise<[string, string]> { - return new Promise((resolve, reject) => { - try { - resolve(execCmd(cmd, options, false, pipeOutput)) - } catch (error) { - console.error(error) - process.exit(1) - // To make the compiler happy. - reject(error) - } - }) -} - -export async function spawnCmdWithExitOnFailure( - cmd: string, - args: string[], - options?: SpawnOptions & { silent?: boolean } -) { - const code = await spawnCmd(cmd, args, options) - if (code !== 0) { - console.error('spawnCmd failed for: ' + [cmd].concat(args).join(' ')) - process.exit(1) - } -} - -export function execBackgroundCmd(cmd: string) { - if (process.env.CELOTOOL_VERBOSE === 'true') { - console.debug('$ ' + cmd) - } - return exec(cmd, { maxBuffer: 1024 * 10000 }, (err, stdout, stderr) => { - if (process.env.CELOTOOL_VERBOSE === 'true') { - console.debug(stdout) - console.error(stderr) - } - if (err) { - console.error(err) - process.exit(1) - } - }) -} - -export async function outputIncludes(cmd: string, matchString: string, matchMessage?: string) { - const [stdout] = await execCmdWithExitOnFailure(cmd) - if (stdout.includes(matchString)) { - if (matchMessage) { - console.info(matchMessage) - } - return true - } - return false -} diff --git a/packages/celotool/src/lib/context-utils.ts b/packages/celotool/src/lib/context-utils.ts deleted file mode 100644 index f14d9eb2c..000000000 --- a/packages/celotool/src/lib/context-utils.ts +++ /dev/null @@ -1,218 +0,0 @@ -import { Argv } from 'yargs' -import { - addCeloEnvMiddleware, - doCheckOrPromptIfStagingOrProduction, - DynamicEnvVar, - envVar, - fetchEnv, - getDynamicEnvVarValue, -} from './env-utils' -import { AksClusterConfig } from './k8s-cluster/aks' -import { BaseClusterConfig, BaseClusterManager, CloudProvider } from './k8s-cluster/base' -import { GCPClusterConfig } from './k8s-cluster/gcp' -import { getClusterManager } from './k8s-cluster/utils' - -/** - * Env vars corresponding to each value for the AksClusterConfig for a particular context - */ -const contextAksClusterConfigDynamicEnvVars: { - [k in keyof Omit]: DynamicEnvVar -} = { - clusterName: DynamicEnvVar.KUBERNETES_CLUSTER_NAME, - subscriptionId: DynamicEnvVar.AZURE_SUBSCRIPTION_ID, - tenantId: DynamicEnvVar.AZURE_TENANT_ID, - resourceGroup: DynamicEnvVar.AZURE_KUBERNETES_RESOURCE_GROUP, - regionName: DynamicEnvVar.AZURE_REGION_NAME, -} - -/** - * Env vars corresponding to each value for the GCPClusterConfig for a particular context - */ -const contextGCPClusterConfigDynamicEnvVars: { - [k in keyof Omit]: DynamicEnvVar -} = { - clusterName: DynamicEnvVar.KUBERNETES_CLUSTER_NAME, - projectName: DynamicEnvVar.GCP_PROJECT_NAME, - zone: DynamicEnvVar.GCP_ZONE, -} - -const clusterConfigGetterByCloudProvider: { - [key in CloudProvider]: (context: string) => BaseClusterConfig -} = { - [CloudProvider.AZURE]: getAksClusterConfig, - [CloudProvider.GCP]: getGCPClusterConfig, -} - -export function getCloudProviderFromContext(context: string): CloudProvider { - for (const cloudProvider of Object.values(CloudProvider)) { - if (context.startsWith(cloudProvider as string)) { - return CloudProvider[cloudProvider as keyof typeof CloudProvider] - } - } - throw Error(`Context ${context} must start with one of ${Object.values(CloudProvider)}`) -} - -/** - * Fetches the env vars for a particular context - * @param context the context to use - * @return an AksClusterConfig for the context - */ -export function getAksClusterConfig(context: string): AksClusterConfig { - const azureDynamicEnvVars = getContextDynamicEnvVarValues( - contextAksClusterConfigDynamicEnvVars, - context - ) - const clusterConfig: AksClusterConfig = { - cloudProvider: CloudProvider.AZURE, - ...azureDynamicEnvVars, - } - return clusterConfig -} - -/** - * Fetches the env vars for a particular context - * @param context the context to use - * @return an GCPClusterConfig for the context - */ -export function getGCPClusterConfig(context: string): GCPClusterConfig { - const gcpDynamicEnvVars = getContextDynamicEnvVarValues( - contextGCPClusterConfigDynamicEnvVars, - context - ) - const clusterConfig: GCPClusterConfig = { - cloudProvider: CloudProvider.GCP, - ...gcpDynamicEnvVars, - } - return clusterConfig -} - -/** - * Helper function used to extract multiple dynamic env vars based on - * an object of dynamic props used for templating. - * @param dynamicEnvVars an object whose values correspond to the desired - * dynamic env vars to fetch. - * @param dynamicProps the properties used for templatin the variables - * @param defaultValues Optional default values if the dynamic env vars are not found - * @return an object with the same keys as dynamicEnvVars, but the values are - * the values of the dynamic env vars for the particular context - */ -export function getDynamicEnvVarValues( - dynamicEnvVars: { [k in keyof T]: DynamicEnvVar }, - dynamicProps: P, - defaultValues?: { [k in keyof T]: string } -): { - [k in keyof T]: string -} { - return Object.keys(dynamicEnvVars).reduce((values: any, k: string) => { - const key = k as keyof T - const dynamicEnvVar = dynamicEnvVars[key] - const defaultValue = defaultValues ? defaultValues[key] : undefined - const value = getDynamicEnvVarValue(dynamicEnvVar, dynamicProps, defaultValue) - return { - ...values, - [key]: value, - } - }, {}) -} - -/** - * Given if the desired context is primary, gives the appropriate OracleAzureContext - * Gives an object with the values of dynamic environment variables for a context. - * @param dynamicEnvVars an object whose values correspond to the desired - * dynamic env vars to fetch. - * @param context The context - * @param defaultValues Optional default values if the dynamic env vars are not found - * @return an object with the same keys as dynamicEnvVars, but the values are - * the values of the dynamic env vars for the particular context - */ -export function getContextDynamicEnvVarValues( - dynamicEnvVars: { [k in keyof T]: DynamicEnvVar }, - context: string, - defaultValues?: { [k in keyof T]: string } -): { - [k in keyof T]: string -} { - return getDynamicEnvVarValues(dynamicEnvVars, { context }, defaultValues) -} - -/** - * Reads the context and switches to the appropriate Azure Cluster - */ -export async function switchToContextCluster( - celoEnv: string, - context: string, - checkOrPromptIfStagingOrProduction: boolean = true, - skipClusterSetup: boolean = false -) { - if (!isValidContext(context)) { - throw Error(`Invalid context, must be one of ${fetchEnv(envVar.CONTEXTS)}`) - } - if (checkOrPromptIfStagingOrProduction) { - await doCheckOrPromptIfStagingOrProduction() - } - const clusterManager: BaseClusterManager = getClusterManagerForContext(celoEnv, context) - await clusterManager.switchToClusterContext(skipClusterSetup, context) - return clusterManager -} - -export function getClusterManagerForContext(celoEnv: string, context: string) { - const cloudProvider: CloudProvider = getCloudProviderFromContext(context) - const clusterConfig = clusterConfigGetterByCloudProvider[cloudProvider](context) - return getClusterManager(cloudProvider, celoEnv, clusterConfig) -} - -export function getClusterConfigForContext(context: string) { - const cloudProvider: CloudProvider = getCloudProviderFromContext(context) - return clusterConfigGetterByCloudProvider[cloudProvider](context) -} - -/** - * yargs argv type for an command that requires a context - */ -export interface ContextArgv { - context: string -} - -/** - * Coerces the value of context to be all upper-case and underscore-separated - * rather than dash-separated. If the resulting context does not match a regex - * requiring all caps, alphanumeric, and dash-only characters - * (must start with letter and not end with an underscore), it will throw. - */ -export function coerceContext(rawContextStr: string) { - const context = rawContextStr.toUpperCase().replace(/-/g, '_') - if (!RegExp('^[A-Z][A-Z0-9_]*[A-Z0-9]$').test(context)) { - throw Error(`Invalid context. Raw ${rawContextStr}, implied ${context}`) - } - return context -} - -export function readableContext(context: string) { - const readable = context.toLowerCase().replace(/_/g, '-') - if (!RegExp('^[A-Z][A-Z0-9_]*[A-Z0-9]$').test(context)) { - throw Error(`Invalid context. Context ${context}, readable ${readable}`) - } - return readable -} - -export function isValidContext(context: string) { - const validContexts = fetchEnv(envVar.CONTEXTS).split(',') - const validContextsCoerced = validContexts.map(coerceContext) - return validContextsCoerced.includes(context) -} - -/** - * Middleware for a context related command. - * Must be one of the contexts specified in the environment - * variable CONTEXTS. - */ -export function addOptionalContextMiddleware(argv: Argv) { - return addCeloEnvMiddleware(argv).option('context', { - description: 'Context to perform the deployment in', - type: 'string', - }) -} - -export function addContextMiddleware(argv: Argv) { - return addOptionalContextMiddleware(argv).coerce('context', coerceContext) -} diff --git a/packages/celotool/src/lib/contract-utils.ts b/packages/celotool/src/lib/contract-utils.ts deleted file mode 100644 index ff5a76f71..000000000 --- a/packages/celotool/src/lib/contract-utils.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { GoldTokenWrapper } from '@celo/contractkit/lib/wrappers/GoldTokenWrapper' -import { StableTokenWrapper } from '@celo/contractkit/lib/wrappers/StableTokenWrapper' -import { BigNumber } from 'bignumber.js' - -export async function convertToContractDecimals( - value: number | BigNumber, - contract: StableTokenWrapper | GoldTokenWrapper -) { - const decimals = new BigNumber(await contract.decimals()) - const one = new BigNumber(10).pow(decimals.toNumber()) - return one.times(value) -} diff --git a/packages/celotool/src/lib/endpoints.ts b/packages/celotool/src/lib/endpoints.ts deleted file mode 100644 index 6cf910396..000000000 --- a/packages/celotool/src/lib/endpoints.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { envVar, fetchEnv } from './env-utils' - -export function getBlockscoutUrl(celoEnv: string) { - return `https://${celoEnv}-blockscout.${fetchEnv(envVar.CLUSTER_DOMAIN_NAME)}.org` -} - -export function getBlockscoutClusterInternalUrl(celoEnv: string) { - return `${celoEnv}-blockscout-web` -} - -export function getEthstatsUrl(celoEnv: string) { - return `https://${celoEnv}-ethstats.${fetchEnv(envVar.CLUSTER_DOMAIN_NAME)}.org` -} - -export function getBlockchainApiUrl(celoEnv: string) { - return `https://${celoEnv}-dot-${fetchEnv(envVar.TESTNET_PROJECT_NAME)}.appspot.com` -} - -export function getGenesisGoogleStorageUrl(celoEnv: string) { - return `https://www.googleapis.com/storage/v1/b/genesis_blocks/o/${celoEnv}?alt=media` -} - -export function getFornoUrl(celoEnv: string) { - return celoEnv === 'rc1' - ? `https://forno.celo.org` - : `https://${celoEnv}-forno.${fetchEnv(envVar.CLUSTER_DOMAIN_NAME)}.org` -} - -export function getFornoWebSocketUrl(celoEnv: string) { - return celoEnv === 'rc1' - ? `wss://forno.celo.org/ws` - : `wss://${celoEnv}-forno.${fetchEnv(envVar.CLUSTER_DOMAIN_NAME)}.org/ws` -} - -export function getFullNodeHttpRpcInternalUrl(celoEnv: string) { - return `http://${celoEnv}-fullnodes-rpc.${celoEnv}.svc.cluster.local:8545` -} - -export function getFullNodeWebSocketRpcInternalUrl(celoEnv: string) { - return `ws://${celoEnv}-fullnodes-rpc.${celoEnv}.svc.cluster.local:8546` -} - -export function getLightNodeHttpRpcInternalUrl(celoEnv: string) { - return `http://${celoEnv}-lightnodes-rpc.${celoEnv}.svc.cluster.local:8545` -} - -export function getLightNodeWebSocketRpcInternalUrl(celoEnv: string) { - return `ws://${celoEnv}-lightnodes-rpc.${celoEnv}.svc.cluster.local:8546` -} diff --git a/packages/celotool/src/lib/env-utils.ts b/packages/celotool/src/lib/env-utils.ts deleted file mode 100644 index 7d6898a17..000000000 --- a/packages/celotool/src/lib/env-utils.ts +++ /dev/null @@ -1,348 +0,0 @@ -import { config } from 'dotenv' -import { existsSync } from 'fs' -import path from 'path' -import prompts from 'prompts' -import yargs from 'yargs' - -export interface CeloEnvArgv extends yargs.Argv { - celoEnv: string -} - -export enum envVar { - BLOCK_TIME = 'BLOCK_TIME', - BLOCKSCOUT_DB_SUFFIX = 'BLOCKSCOUT_DB_SUFFIX', - BLOCKSCOUT_DB_NEW_SUFFIX = 'BLOCKSCOUT_DB_NEW_SUFFIX', - BLOCKSCOUT_DOCKER_IMAGE_TAG = 'BLOCKSCOUT_DOCKER_IMAGE_TAG', - CELOCLI_STANDALONE_IMAGE_REPOSITORY = 'CELOCLI_STANDALONE_IMAGE_REPOSITORY', - CELOCLI_STANDALONE_IMAGE_TAG = 'CELOCLI_STANDALONE_IMAGE_TAG', - CELOSTATS_BANNED_ADDRESSES = 'CELOSTATS_BANNED_ADDRESSES', - CELOSTATS_FRONTEND_DOCKER_IMAGE_REPOSITORY = 'CELOSTATS_FRONTEND_DOCKER_IMAGE_REPOSITORY', - CELOSTATS_FRONTEND_DOCKER_IMAGE_TAG = 'CELOSTATS_FRONTEND_DOCKER_IMAGE_TAG', - CELOSTATS_RESERVED_ADDRESSES = 'CELOSTATS_RESERVED_ADDRESSES', - CELOSTATS_SERVER_DOCKER_IMAGE_REPOSITORY = 'CELOSTATS_SERVER_DOCKER_IMAGE_REPOSITORY', - CELOSTATS_SERVER_DOCKER_IMAGE_TAG = 'CELOSTATS_SERVER_DOCKER_IMAGE_TAG', - CELOSTATS_TRUSTED_ADDRESSES = 'CELOSTATS_TRUSTED_ADDRESSES', - CELOTOOL_CELOENV = 'CELOTOOL_CELOENV', - CELOTOOL_CONFIRMED = 'CELOTOOL_CONFIRMED', - CELOTOOL_DOCKER_IMAGE_REPOSITORY = 'CELOTOOL_DOCKER_IMAGE_REPOSITORY', - CELOTOOL_DOCKER_IMAGE_TAG = 'CELOTOOL_DOCKER_IMAGE_TAG', - CHAOS_TEST_DURATION = 'CHAOS_TEST_DURATION', - CHAOS_TEST_INTERVAL = 'CHAOS_TEST_INTERVAL', - CHAOS_TEST_KILL_INTERVAL = 'CHAOS_TEST_KILL_INTERVAL', - CHAOS_TEST_NETWORK_DELAY = 'CHAOS_TEST_NETWORK_DELAY', - CHAOS_TEST_NETWORK_JITTER = 'CHAOS_TEST_NETWORK_JITTER', - CHAOS_TEST_NETWORK_LOSS = 'CHAOS_TEST_NETWORK_LOSS', - CHAOS_TEST_NETWORK_RATE = 'CHAOS_TEST_NETWORK_RATE', - CHURRITO_BLOCK = 'CHURRITO_BLOCK', - CLUSTER_CREATION_FLAGS = 'CLUSTER_CREATION_FLAGS', - CLUSTER_DOMAIN_NAME = 'CLUSTER_DOMAIN_NAME', - CONSENSUS_TYPE = 'CONSENSUS_TYPE', - CONTEXTS = 'CONTEXTS', - DONUT_BLOCK = 'DONUT_BLOCK', - E2E_TESTS_FORCE_USE_MYCELO = 'E2E_TESTS_FORCE_USE_MYCELO', - ENV_TYPE = 'ENV_TYPE', - EPOCH = 'EPOCH', - ESPRESSO_BLOCK = 'ESPRESSO_BLOCK', - FAUCET_CUSD_WEI = 'FAUCET_CUSD_WEI', - FAUCET_GENESIS_ACCOUNTS = 'FAUCET_GENESIS_ACCOUNTS', - FAUCET_GENESIS_BALANCE = 'FAUCET_GENESIS_BALANCE', - FORNO_BANNED_CIDR = 'FORNO_BANNED_CIDR', - FORNO_DOMAINS = 'FORNO_DOMAINS', - FORNO_FULL_NODE_CONTEXTS = 'FORNO_FULL_NODE_CONTEXTS', - FORNO_VPC_NETWORK_NAME = 'FORNO_VPC_NETWORK_NAME', - FULL_NODE_READINESS_CHECK_BLOCK_AGE = 'FULL_NODE_READINESS_CHECK_BLOCK_AGE', - GENESIS_ACCOUNTS = 'GENESIS_ACCOUNTS', - GETH_ACCOUNT_SECRET = 'GETH_ACCOUNT_SECRET', - GETH_BOOTNODE_DOCKER_IMAGE_REPOSITORY = 'GETH_BOOTNODE_DOCKER_IMAGE_REPOSITORY', - GETH_BOOTNODE_DOCKER_IMAGE_TAG = 'GETH_BOOTNODE_DOCKER_IMAGE_TAG', - GETH_BOOTNODE_OVERWRITE_PKEY = 'GETH_BOOTNODE_OVERWRITE_PKEY', - GETH_DEBUG = 'GETH_DEBUG', - GETH_ENABLE_METRICS = 'GETH_ENABLE_METRICS', - GETH_NODE_DOCKER_IMAGE_REPOSITORY = 'GETH_NODE_DOCKER_IMAGE_REPOSITORY', - GETH_NODE_DOCKER_IMAGE_TAG = 'GETH_NODE_DOCKER_IMAGE_TAG', - GETH_NODES_SSD_DISKS = 'GETH_NODES_SSD_DISKS', - GETH_USE_MYCELO = 'GETH_USE_MYCELO', - GETH_MYCELO_COMMIT = 'GETH_MYCELO_COMMIT', - GETH_VERBOSITY = 'GETH_VERBOSITY', - GOOGLE_APPLICATION_CREDENTIALS = 'GOOGLE_APPLICATION_CREDENTIALS', - GRAFANA_CLOUD_PROJECT_ID = 'GRAFANA_CLOUD_PROJECT_ID', - GRAFANA_CLOUD_SECRET_NAME = 'GRAFANA_CLOUD_SECRET_NAME', - GRAFANA_CLOUD_SECRET_VERSION = 'GRAFANA_CLOUD_SECRET_VERSION', - GRAFANA_LOCAL_ADMIN_PASSWORD = 'GRAFANA_LOCAL_ADMIN_PASSWORD', - GRAFANA_LOCAL_OAUTH2_CLIENT_ID = 'GRAFANA_LOCAL_OAUTH2_CLIENT_ID', - GRAFANA_LOCAL_OAUTH2_CLIENT_SECRET = 'GRAFANA_LOCAL_OAUTH2_CLIENT_SECRET', - IN_MEMORY_DISCOVERY_TABLE = 'IN_MEMORY_DISCOVERY_TABLE', - ISTANBUL_REQUEST_TIMEOUT_MS = 'ISTANBUL_REQUEST_TIMEOUT_MS', - KUBECONFIG = 'KUBECONFIG', - KUBERNETES_CLUSTER_NAME = 'KUBERNETES_CLUSTER_NAME', - KUBERNETES_CLUSTER_ZONE = 'KUBERNETES_CLUSTER_ZONE', - LEADERBOARD_CREDENTIALS = 'LEADERBOARD_CREDENTIALS', - LEADERBOARD_DOCKER_IMAGE_REPOSITORY = 'LEADERBOARD_DOCKER_IMAGE_REPOSITORY', - LEADERBOARD_DOCKER_IMAGE_TAG = 'LEADERBOARD_DOCKER_IMAGE_TAG', - LEADERBOARD_SHEET = 'LEADERBOARD_SHEET', - LEADERBOARD_TOKEN = 'LEADERBOARD_TOKEN', - LOAD_TEST_CLIENTS = 'LOAD_TEST_CLIENTS', - LOAD_TEST_THREADS = 'LOAD_TEST_THREADS', - LOAD_TEST_GENESIS_BALANCE = 'LOAD_TEST_GENESIS_BALANCE', - LOAD_TEST_TX_DELAY_MS = 'LOAD_TEST_TX_DELAY_MS', - LOAD_TEST_USE_RANDOM_RECIPIENT = 'LOAD_TEST_USE_RANDOM_RECIPIENT', - LOKI_URL = 'LOKI_URL', - LOKI_KEY = 'LOKI_KEY', - LOKI_USERNAME = 'LOKI_USERNAME', - LOOKBACK = 'LOOKBACK', - MNEMONIC = 'MNEMONIC', - MOBILE_WALLET_PLAYSTORE_LINK = 'MOBILE_WALLET_PLAYSTORE_LINK', - MOCK_ORACLE_CRON_SCHEDULE = 'MOCK_ORACLE_CRON_SCHEDULE', - MOCK_ORACLE_DOCKER_IMAGE_REPOSITORY = 'MOCK_ORACLE_DOCKER_IMAGE_REPOSITORY', - MOCK_ORACLE_DOCKER_IMAGE_TAG = 'MOCK_ORACLE_DOCKER_IMAGE_TAG', - MOCK_ORACLE_GENESIS_BALANCE = 'MOCK_ORACLE_GENESIS_BALANCE', - NETWORK_ID = 'NETWORK_ID', - NODE_DISK_SIZE_GB = 'NODE_DISK_SIZE_GB', - ODIS_SIGNER_DOCKER_IMAGE_REPOSITORY = 'ODIS_SIGNER_DOCKER_IMAGE_REPOSITORY', - ODIS_SIGNER_DOCKER_IMAGE_TAG = 'ODIS_SIGNER_DOCKER_IMAGE_TAG', - ODIS_SIGNER_BLOCKCHAIN_PROVIDER = 'ODIS_SIGNER_BLOCKCHAIN_PROVIDER', - ODIS_SIGNER_DOMAINS_API_ENABLED = 'ODIS_SIGNER_DOMAINS_API_ENABLED', - ODIS_SIGNER_PNP_API_ENABLED = 'ODIS_SIGNER_PNP_API_ENABLED', - ORACLE_DOCKER_IMAGE_REPOSITORY = 'ORACLE_DOCKER_IMAGE_REPOSITORY', - ORACLE_DOCKER_IMAGE_TAG = 'ORACLE_DOCKER_IMAGE_TAG', - ORACLE_UNUSED_ORACLE_ADDRESSES = 'ORACLE_UNUSED_ORACLE_ADDRESSES', - ORACLE_FX_ADAPTERS_API_KEYS = 'ORACLE_FX_ADAPTERS_API_KEYS', - PRIVATE_NODE_DISK_SIZE_GB = 'PRIVATE_NODE_DISK_SIZE_GB', - PRIVATE_TX_NODES = 'PRIVATE_TX_NODES', - PROMETHEUS_DISABLE_STACKDRIVER_SIDECAR = 'PROMETHEUS_DISABLE_STACKDRIVER_SIDECAR', - PROMETHEUS_REMOTE_WRITE_PASSWORD = 'PROMETHEUS_REMOTE_WRITE_PASSWORD', - PROMETHEUS_REMOTE_WRITE_URL = 'PROMETHEUS_REMOTE_WRITE_URL', - PROMETHEUS_REMOTE_WRITE_USERNAME = 'PROMETHEUS_REMOTE_WRITE_USERNAME', - PROXIED_VALIDATORS = 'PROXIED_VALIDATORS', - PROXY_ROLLING_UPDATE_PARTITION = 'PROXY_ROLLING_UPDATE_PARTITION', - SECONDARIES_ROLLING_UPDATE_PARTITION = 'SECONDARIES_ROLLING_UPDATE_PARTITION', - STATIC_IPS_FOR_GETH_NODES = 'STATIC_IPS_FOR_GETH_NODES', - TESTNET_PROJECT_NAME = 'TESTNET_PROJECT_NAME', - TIMESTAMP = 'TIMESTAMP', - TRANSACTION_METRICS_EXPORTER_BLOCK_INTERVAL = 'TRANSACTION_METRICS_EXPORTER_BLOCK_INTERVAL', - TRANSACTION_METRICS_EXPORTER_DOCKER_IMAGE_REPOSITORY = 'TRANSACTION_METRICS_EXPORTER_DOCKER_IMAGE_REPOSITORY', - TRANSACTION_METRICS_EXPORTER_DOCKER_IMAGE_TAG = 'TRANSACTION_METRICS_EXPORTER_DOCKER_IMAGE_TAG', - TRANSACTION_METRICS_EXPORTER_FROM_BLOCK = 'TRANSACTION_METRICS_EXPORTER_FROM_BLOCK', - TRANSACTION_METRICS_EXPORTER_SUFFIX = 'TRANSACTION_METRICS_EXPORTER_SUFFIX', - TRANSACTION_METRICS_EXPORTER_TO_BLOCK = 'TRANSACTION_METRICS_EXPORTER_TO_BLOCK', - TRANSACTION_METRICS_EXPORTER_WATCH_ADDRESS = 'TRANSACTION_METRICS_EXPORTER_WATCH_ADDRESS', - TX_NODES = 'TX_NODES', - TX_NODES_PRIVATE_ROLLING_UPDATE_PARTITION = 'TX_NODES_PRIVATE_ROLLING_UPDATE_PARTITION', - TX_NODES_ROLLING_UPDATE_PARTITION = 'TX_NODES_ROLLING_UPDATE_PARTITION', - USE_GSTORAGE_DATA = 'USE_GSTORAGE_DATA', - VALIDATOR_GENESIS_BALANCE = 'VALIDATOR_GENESIS_BALANCE', - VALIDATOR_PROXY_COUNTS = 'VALIDATOR_PROXY_COUNTS', - VALIDATOR_ZERO_GENESIS_BALANCE = 'VALIDATOR_ZERO_GENESIS_BALANCE', - VALIDATORS = 'VALIDATORS', - VALIDATORS_ROLLING_UPDATE_PARTITION = 'VALIDATORS_ROLLING_UPDATE_PARTITION', - VOTING_BOT_BALANCE = 'VOTING_BOT_BALANCE', - VOTING_BOT_CHANGE_BASELINE = 'VOTING_BOT_CHANGE_BASELINE', - VOTING_BOT_CRON_SCHEDULE = 'VOTING_BOT_CRON_SCHEDULE', - VOTING_BOT_EXPLORE_PROBABILITY = 'VOTING_BOT_EXPLORE_PROBABILITY', - VOTING_BOT_SCORE_SENSITIVITY = 'VOTING_BOT_SCORE_SENSITIVITY', - VOTING_BOT_WAKE_PROBABILITY = 'VOTING_BOT_WAKE_PROBABILITY', - VOTING_BOTS = 'VOTING_BOTS', - WALLET_CONNECT_IMAGE_REPOSITORY = 'WALLET_CONNECT_IMAGE_REPOSITORY', - WALLET_CONNECT_IMAGE_TAG = 'WALLET_CONNECT_IMAGE_TAG', - WALLET_CONNECT_REDIS_CLUSTER_ENABLED = 'WALLET_CONNECT_REDIS_CLUSTER_ENABLED', - WALLET_CONNECT_REDIS_CLUSTER_USEPASSWORD = 'WALLET_CONNECT_REDIS_CLUSTER_USEPASSWORD', -} - -/** - * Dynamic env vars are env var names that can be dynamically constructed - * using templates. - */ - -export enum DynamicEnvVar { - AZURE_SUBSCRIPTION_ID = '{{ context }}_AZURE_SUBSCRIPTION_ID', - AZURE_KUBERNETES_RESOURCE_GROUP = '{{ context }}_AZURE_KUBERNETES_RESOURCE_GROUP', - AZURE_REGION_NAME = '{{ context }}_AZURE_REGION_NAME', - AZURE_TENANT_ID = '{{ context }}_AZURE_TENANT_ID', - FULL_NODES_COUNT = '{{ context }}_FULL_NODES_COUNT', - FULL_NODES_DISK_SIZE = '{{ context }}_FULL_NODES_DISK_SIZE', - FULL_NODES_GETH_GC_MODE = '{{ context }}_FULL_NODES_GETH_GC_MODE', - FULL_NODES_NODEKEY_DERIVATION_STRING = '{{ context }}_FULL_NODES_NODEKEY_DERIVATION_STRING', - FULL_NODES_ROLLING_UPDATE_PARTITION = '{{ context }}_FULL_NODES_ROLLING_UPDATE_PARTITION', - FULL_NODES_RPC_API_METHODS = '{{ context }}_FULL_NODES_RPC_API_METHODS', - FULL_NODES_STATIC_NODES_FILE_SUFFIX = '{{ context }}_FULL_NODES_STATIC_NODES_FILE_SUFFIX', - FULL_NODES_USE_GSTORAGE_DATA = '{{ context }}_FULL_NODES_USE_GSTORAGE_DATA', - FULL_NODES_WS_PORT = '{{ context }}_FULL_NODES_WS_PORT', - GCP_PROJECT_NAME = '{{ context }}_GCP_PROJECT_NAME', - GCP_ZONE = '{{ context }}_GCP_ZONE', - KUBERNETES_CLUSTER_NAME = '{{ context }}_KUBERNETES_CLUSTER_NAME', - ORACLE_ADDRESS_AZURE_KEY_VAULTS = '{{ context }}_{{ currencyPair }}_ORACLE_ADDRESS_AZURE_KEY_VAULTS', - ORACLE_ADDRESSES_FROM_MNEMONIC_COUNT = '{{ context }}_{{ currencyPair}}_ORACLE_ADDRESSES_FROM_MNEMONIC_COUNT', - ODIS_SIGNER_BLOCKCHAIN_API_KEY = '{{ context }}_ODIS_SIGNER_BLOCKCHAIN_API_KEY', - ODIS_SIGNER_AZURE_KEYVAULT_NAME = '{{ context }}_ODIS_SIGNER_AZURE_KEYVAULT_NAME', - ODIS_SIGNER_AZURE_KEYVAULT_PNP_KEY_NAME_BASE = '{{ context }}_ODIS_SIGNER_AZURE_KEYVAULT_PNP_KEY_NAME_BASE', - ODIS_SIGNER_AZURE_KEYVAULT_PNP_KEY_LATEST_VERSION = '{{ context }}_ODIS_SIGNER_AZURE_KEYVAULT_PNP_KEY_LATEST_VERSION', - ODIS_SIGNER_AZURE_KEYVAULT_DOMAINS_KEY_NAME_BASE = '{{ context }}_ODIS_SIGNER_AZURE_KEYVAULT_DOMAINS_KEY_NAME_BASE', - ODIS_SIGNER_AZURE_KEYVAULT_DOMAINS_KEY_LATEST_VERSION = '{{ context }}_ODIS_SIGNER_AZURE_KEYVAULT_DOMAINS_KEY_LATEST_VERSION', - ODIS_SIGNER_DOMAINS_API_ENABLED = '{{ context }}_ODIS_SIGNER_DOMAINS_API_ENABLED', - ODIS_SIGNER_PHONE_NUMBER_PRIVACY_API_ENABLED = '{{ context }}_ODIS_SIGNER_PNP_API_ENABLED', - ODIS_SIGNER_DB_HOST = '{{ context }}_ODIS_SIGNER_DB_HOST', - ODIS_SIGNER_DB_PORT = '{{ context }}_ODIS_SIGNER_DB_PORT', - ODIS_SIGNER_DB_USERNAME = '{{ context }}_ODIS_SIGNER_DB_USERNAME', - ODIS_SIGNER_DB_PASSWORD = '{{ context }}_ODIS_SIGNER_DB_PASSWORD', - ODIS_SIGNER_LOG_LEVEL = 'ODIS_SIGNER_LOG_LEVEL', - ODIS_SIGNER_LOG_FORMAT = 'ODIS_SIGNER_LOG_FORMAT', - ODIS_NETWORK = '{{ context }}_ODIS_NETWORK', - PROM_SIDECAR_DISABLED = '{{ context }}_PROM_SIDECAR_DISABLED', - PROM_SIDECAR_GCP_PROJECT = '{{ context }}_PROM_SIDECAR_GCP_PROJECT', - PROM_SIDECAR_GCP_REGION = '{{ context }}_PROM_SIDECAR_GCP_REGION', - PROM_SCRAPE_JOB_NAME = '{{ context }}_PROM_SCRAPE_JOB_NAME', - PROM_SCRAPE_LABELS = '{{ context }}_PROM_SCRAPE_LABELS', - PROM_SCRAPE_TARGETS = '{{ context }}_PROM_SCRAPE_TARGETS', - PROM_REMOTE_WRITE_PASSWORD = '{{ context }}_PROM_REMOTE_WRITE_PASSWORD', - PROM_REMOTE_WRITE_USERNAME = '{{ context }}_PROM_REMOTE_WRITE_USERNAME', - PROM_REMOTE_WRITE_URL = '{{ context }}_PROM_REMOTE_WRITE_URL', -} - -export enum envTypes { - DEVELOPMENT = 'development', - INTEGRATION = 'integration', - STAGING = 'staging', - PRODUCTION = 'production', -} - -export function fetchEnv(env: string, customErrorMessage?: string): string { - if (process.env[env] === undefined) { - console.error( - customErrorMessage !== undefined ? customErrorMessage : `Requires variable ${env} to be set` - ) - process.exit(1) - } - return process.env[env]! -} - -export const monorepoRoot = path.resolve(process.cwd(), './../..') -export const genericEnvFilePath = path.resolve(monorepoRoot, '.env') - -export function getEnvFile(celoEnv: string, envBegining: string = '') { - const filePath: string = path.resolve(monorepoRoot, `.env${envBegining}.${celoEnv}`) - if (existsSync(filePath)) { - return filePath - } else { - return `${genericEnvFilePath}${envBegining}` - } -} - -export function fetchEnvOrFallback(env: string, fallback: string) { - return process.env[env] || fallback -} - -export function validateAndSwitchToEnv(celoEnv: string) { - if (!isValidCeloEnv(celoEnv)) { - console.error( - `${celoEnv} does not conform to specification ^[a-z][a-z0-9]*$. We need to it to conform to that regex because it is used as URL components, Kubernetes namespace names, keys in configuration objects, etc.` - ) - process.exit(1) - } - - const envResult = config({ path: getEnvFile(celoEnv) }) - const envMemonicResult = config({ path: getEnvFile(celoEnv, '.mnemonic') }) - - const convinedParsedResults: { [s: string]: string } = {} - - for (const result of [envResult, envMemonicResult]) { - if (result.error) { - throw result.error - } - Object.assign(convinedParsedResults, result.parsed) - } - - // Override any env variables that weren't set by config. - if (convinedParsedResults) { - for (const k of Object.keys(convinedParsedResults)) { - process.env[k] = convinedParsedResults[k] - } - } - - process.env.CELOTOOL_CELOENV = celoEnv -} - -export function isProduction() { - return fetchEnv(envVar.ENV_TYPE).toLowerCase() === envTypes.PRODUCTION -} - -export function isValidCeloEnv(celoEnv: string) { - return new RegExp('^[a-z][a-z0-9]*$').test(celoEnv) -} - -export function getDynamicEnvVarValue( - dynamicEnvVar: DynamicEnvVar, - templateValues: any, - defaultValue?: string -) { - const envVarName = getDynamicEnvVarName(dynamicEnvVar, templateValues) - return defaultValue !== undefined - ? fetchEnvOrFallback(envVarName, defaultValue) - : fetchEnv(envVarName) -} - -/** - * Replaces a dynamic env var's template strings with values from an object. - * For each template value that was given, it replaces the corresponding template - * string. - * For example, if the DynamicEnvVar is: - * '{{ thing }}-is-{{noun}}!!!' - * and templateValues is the object: - * { thing: 'celo', noun: 'cool' } - * then we can expect this function to return the string: - * 'celo-is-cool!!!' - * Returns the name of the env var. - */ -export function getDynamicEnvVarName(dynamicEnvVar: DynamicEnvVar, templateValues: any) { - return Object.keys(templateValues).reduce((agg: string, templateKey: string) => { - return agg.replace(new RegExp(`{{ *${templateKey} *}}`, 'g'), templateValues[templateKey]) - }, dynamicEnvVar) -} - -function celoEnvMiddleware(argv: CeloEnvArgv) { - validateAndSwitchToEnv(argv.celoEnv) -} - -export async function doCheckOrPromptIfStagingOrProduction() { - if (process.env.CELOTOOL_CONFIRMED !== 'true' && isProduction()) { - await confirmAction( - `You are about to apply a possibly irreversible action on a production env: ${process.env.CELOTOOL_CELOENV}. Are you sure?` - ) - process.env.CELOTOOL_CONFIRMED = 'true' - } -} - -export async function confirmAction( - message: string, - onConfirmFailed?: () => Promise, - onConfirmSuccess?: () => Promise -) { - const response = await prompts({ - type: 'confirm', - name: 'confirmation', - message: `${message} (y/n)`, - }) - if (!response.confirmation) { - console.info('Aborting due to user response') - if (onConfirmFailed) { - await onConfirmFailed() - } - process.exit(0) - } - if (onConfirmSuccess) { - await onConfirmSuccess() - } -} - -export function addCeloEnvMiddleware(argv: yargs.Argv) { - return ( - argv - .option('celo-env', { - demand: 'Please specify a valid CELO_ENV', - alias: 'e', - required: true, - description: 'the environment in which you want to execute this command', - }) - // @ts-ignore Since we pass it right above, we know that celoEnv will be there at runtime - .middleware([celoEnvMiddleware]) - ) -} diff --git a/packages/celotool/src/lib/fullnodes.ts b/packages/celotool/src/lib/fullnodes.ts deleted file mode 100644 index bdbbae673..000000000 --- a/packages/celotool/src/lib/fullnodes.ts +++ /dev/null @@ -1,186 +0,0 @@ -import stringHash from 'string-hash' -import { - getAksClusterConfig, - getCloudProviderFromContext, - getContextDynamicEnvVarValues, - getGCPClusterConfig, -} from './context-utils' -import { DynamicEnvVar, envVar, fetchEnv, getDynamicEnvVarValue } from './env-utils' -import { CloudProvider } from './k8s-cluster/base' -import { AksFullNodeDeploymentConfig } from './k8s-fullnode/aks' -import { BaseFullNodeDeploymentConfig } from './k8s-fullnode/base' -import { GCPFullNodeDeploymentConfig } from './k8s-fullnode/gcp' -import { getFullNodeDeployer } from './k8s-fullnode/utils' -import { uploadStaticNodesToGoogleStorage } from './testnet-utils' - -/** - * Env vars corresponding to values required for a BaseFullNodeDeploymentConfig - */ -const contextFullNodeDeploymentEnvVars: { - [k in keyof BaseFullNodeDeploymentConfig]: DynamicEnvVar -} = { - diskSizeGb: DynamicEnvVar.FULL_NODES_DISK_SIZE, - replicas: DynamicEnvVar.FULL_NODES_COUNT, - rollingUpdatePartition: DynamicEnvVar.FULL_NODES_ROLLING_UPDATE_PARTITION, - rpcApis: DynamicEnvVar.FULL_NODES_RPC_API_METHODS, - gcMode: DynamicEnvVar.FULL_NODES_GETH_GC_MODE, - wsPort: DynamicEnvVar.FULL_NODES_WS_PORT, - useGstoreData: DynamicEnvVar.FULL_NODES_USE_GSTORAGE_DATA, -} - -/** - * Maps each cloud provider to the correct function to get the appropriate full - * node deployment config - */ -const deploymentConfigGetterByCloudProvider: { - [key in CloudProvider]: (context: string) => BaseFullNodeDeploymentConfig -} = { - [CloudProvider.AZURE]: getAksFullNodeDeploymentConfig, - [CloudProvider.GCP]: getGCPFullNodeDeploymentConfig, -} - -/** - * Gets the appropriate cloud platform's full node deployer given the celoEnv - * and context. - */ -export function getFullNodeDeployerForContext( - celoEnv: string, - context: string, - generateNodeKeys: boolean, - createNEG: boolean -) { - const cloudProvider: CloudProvider = getCloudProviderFromContext(context) - let deploymentConfig = deploymentConfigGetterByCloudProvider[cloudProvider](context) - if (generateNodeKeys) { - deploymentConfig = { - ...deploymentConfig, - nodeKeyGenerationInfo: { - mnemonic: fetchEnv(envVar.MNEMONIC), - derivationIndex: stringHash(getNodeKeyDerivationString(context)), - }, - } - } - if (createNEG) { - if (cloudProvider !== CloudProvider.GCP) { - throw Error('Cannot create NEG for cloud providers other than GCP') - } - deploymentConfig = { - ...deploymentConfig, - createNEG: true, - } as unknown as GCPFullNodeDeploymentConfig // make typescript happy - } - return getFullNodeDeployer(cloudProvider, celoEnv, deploymentConfig) -} - -/** - * Uses the appropriate cloud platform's full node deployer to install the full - * node chart. - */ -export async function installFullNodeChart( - celoEnv: string, - context: string, - staticNodes: boolean = false, - createNEG: boolean = false -) { - const deployer = getFullNodeDeployerForContext(celoEnv, context, staticNodes, createNEG) - const enodes = await deployer.installChart(context) - if (enodes) { - await uploadStaticNodeEnodes(celoEnv, context, enodes) - } -} - -/** - * Uses the appropriate cloud platform's full node deployer to upgrade the full - * node chart. - */ -export async function upgradeFullNodeChart( - celoEnv: string, - context: string, - reset: boolean, - generateNodeKeys: boolean = false, - createNEG: boolean = false -) { - const deployer = getFullNodeDeployerForContext(celoEnv, context, generateNodeKeys, createNEG) - const enodes = await deployer.upgradeChart(context, reset) - if (enodes) { - await uploadStaticNodeEnodes(celoEnv, context, enodes) - } -} - -/** - * Uses the appropriate cloud platform's full node deployer to remove the full - * node chart. - */ -export async function removeFullNodeChart(celoEnv: string, context: string) { - const deployer = getFullNodeDeployerForContext(celoEnv, context, false, false) - await deployer.removeChart() - // Remove any previous static nodes - await uploadStaticNodeEnodes(celoEnv, context, []) -} - -function uploadStaticNodeEnodes(celoEnv: string, context: string, enodes: string[]) { - const suffix = getStaticNodesFileSuffix(context) - // Use mainnet instead of rc1 - const env = celoEnv === 'rc1' ? 'mainnet' : celoEnv - return uploadStaticNodesToGoogleStorage(`${env}.${suffix}`, enodes) -} - -function getNodeKeyDerivationString(context: string) { - return getDynamicEnvVarValue(DynamicEnvVar.FULL_NODES_NODEKEY_DERIVATION_STRING, { - context, - }) -} - -function getStaticNodesFileSuffix(context: string) { - return getDynamicEnvVarValue(DynamicEnvVar.FULL_NODES_STATIC_NODES_FILE_SUFFIX, { - context, - }) -} - -/** - * Returns the BaseFullNodeDeploymentConfig that is not specific to a cloud - * provider for a context. - */ -function getFullNodeDeploymentConfig(context: string): BaseFullNodeDeploymentConfig { - const fullNodeDeploymentEnvVarValues = getContextDynamicEnvVarValues( - contextFullNodeDeploymentEnvVars, - context - ) - - const fullNodeDeploymentConfig: BaseFullNodeDeploymentConfig = { - diskSizeGb: parseInt(fullNodeDeploymentEnvVarValues.diskSizeGb, 10), - replicas: parseInt(fullNodeDeploymentEnvVarValues.replicas, 10), - rollingUpdatePartition: parseInt(fullNodeDeploymentEnvVarValues.rollingUpdatePartition, 10), - rpcApis: fullNodeDeploymentEnvVarValues.rpcApis, - gcMode: fullNodeDeploymentEnvVarValues.gcMode, - wsPort: parseInt(fullNodeDeploymentEnvVarValues.wsPort, 10), - useGstoreData: fullNodeDeploymentEnvVarValues.useGstoreData, - } - return fullNodeDeploymentConfig -} - -/** - * For a given context, returns the appropriate AksFullNodeDeploymentConfig - */ -function getAksFullNodeDeploymentConfig(context: string): AksFullNodeDeploymentConfig { - const fullNodeDeploymentConfig: BaseFullNodeDeploymentConfig = - getFullNodeDeploymentConfig(context) - return { - ...fullNodeDeploymentConfig, - clusterConfig: getAksClusterConfig(context), - } -} - -/** - * For a given context, returns the appropriate getGCPFullNodeDeploymentConfig - */ -function getGCPFullNodeDeploymentConfig(context: string): GCPFullNodeDeploymentConfig { - const fullNodeDeploymentConfig: BaseFullNodeDeploymentConfig = - getFullNodeDeploymentConfig(context) - return { - ...fullNodeDeploymentConfig, - clusterConfig: getGCPClusterConfig(context), - // Default value - createNEG: false, - } -} diff --git a/packages/celotool/src/lib/gcloud_utils.ts b/packages/celotool/src/lib/gcloud_utils.ts deleted file mode 100644 index d617be46e..000000000 --- a/packages/celotool/src/lib/gcloud_utils.ts +++ /dev/null @@ -1,151 +0,0 @@ -import { SecretManagerServiceClient } from '@google-cloud/secret-manager' -import { execCmd } from './cmd-utils' -import { DynamicEnvVar, envVar, fetchEnv, getDynamicEnvVarValue } from './env-utils' - -export async function getCurrentGcloudAccount() { - const [output] = await execCmd('gcloud config get-value account') - if (output.trim() === '') { - throw new Error('No Gcloud account set') - } - return output.trim() -} - -async function ensureGcloudInstalled() { - try { - await execCmd(`gcloud version`) - } catch (error) { - console.error('Gcloud is not installed') - console.error(error) - process.exit(1) - } -} - -export async function ensureAuthenticatedGcloudAccount() { - await ensureGcloudInstalled() - try { - await getCurrentGcloudAccount() - } catch (error) { - // Try authenticating with a Keyfile under GOOGLE_APPLICATION_CREDENTIALS - - console.debug('Authenticating gcloud with keyfile') - await execCmd( - `gcloud auth activate-service-account --key-file=${fetchEnv( - envVar.GOOGLE_APPLICATION_CREDENTIALS, - 'gcloud is not authenticated, and thus needs GOOGLE_APPLICATION_CREDENTIALS for automatic authentication' - )}` - ) - } - - try { - await getCurrentGcloudAccount() - } catch (error) { - console.error('Could not setup gcloud with authentication') - process.exit(1) - } -} - -export async function linkSAForWorkloadIdentity(celoEnv: string, context: string) { - if ( - getDynamicEnvVarValue( - DynamicEnvVar.FULL_NODES_USE_GSTORAGE_DATA, - { context }, - 'false' - ).toLowerCase() === 'true' - ) { - await execCmd( - `gcloud iam service-accounts add-iam-policy-binding --project ${fetchEnv( - envVar.TESTNET_PROJECT_NAME - )} \ - --role roles/iam.workloadIdentityUser \ - --member "serviceAccount:${fetchEnv( - envVar.TESTNET_PROJECT_NAME - )}.svc.id.goog[${celoEnv}/gcloud-storage-access]" chaindata-download@${fetchEnv( - envVar.TESTNET_PROJECT_NAME - )}.iam.gserviceaccount.com` - ) - } -} - -export async function delinkSAForWorkloadIdentity(celoEnv: string, context: string) { - if ( - getDynamicEnvVarValue( - DynamicEnvVar.FULL_NODES_USE_GSTORAGE_DATA, - { context }, - 'false' - ).toLowerCase() === 'true' - ) { - await execCmd( - `gcloud iam service-accounts remove-iam-policy-binding --project ${fetchEnv( - envVar.TESTNET_PROJECT_NAME - )} \ - --role roles/iam.workloadIdentityUser \ - --member "serviceAccount:${fetchEnv( - envVar.TESTNET_PROJECT_NAME - )}.svc.id.goog[${celoEnv}/gcloud-storage-access]" chaindata-download@${fetchEnv( - envVar.TESTNET_PROJECT_NAME - )}.iam.gserviceaccount.com` - ) - } -} - -export async function kubectlAnnotateKSA(celoEnv: string, context: string) { - if ( - getDynamicEnvVarValue( - DynamicEnvVar.FULL_NODES_USE_GSTORAGE_DATA, - { context }, - 'false' - ).toLowerCase() === 'true' - ) { - await execCmd( - `kubectl annotate serviceaccount \ - --namespace ${celoEnv} \ - gcloud-storage-access \ - --overwrite \ - iam.gke.io/gcp-service-account=chaindata-download@${fetchEnv( - envVar.TESTNET_PROJECT_NAME - )}.iam.gserviceaccount.com` - ) - } -} - -export async function removeKubectlAnnotateKSA(celoEnv: string, context: string) { - if ( - getDynamicEnvVarValue( - DynamicEnvVar.FULL_NODES_USE_GSTORAGE_DATA, - { context }, - 'false' - ).toLowerCase() === 'true' - ) { - await execCmd( - `kubectl annotate serviceaccount \ - --namespace ${celoEnv} \ - gcloud-storage-access \ - iam.gke.io/gcp-service-account=chaindata-download@${fetchEnv( - envVar.TESTNET_PROJECT_NAME - )}.iam.gserviceaccount.com-` - ) - } -} - -export async function accessSecretVersion( - projectId: string, - secretName: string, - secretVersion: string -) { - try { - const client = new SecretManagerServiceClient() - const [version] = await client.accessSecretVersion({ - name: `projects/${projectId}/secrets/${secretName}/versions/${secretVersion}`, - }) - - const privateKey = version?.payload?.data?.toString()! - - if (!privateKey) { - throw new Error('Key is empty or undefined') - } - - return privateKey - } catch (error) { - console.info('Error retrieving key') - } -} diff --git a/packages/celotool/src/lib/generate_utils.ts b/packages/celotool/src/lib/generate_utils.ts deleted file mode 100644 index 6da7be109..000000000 --- a/packages/celotool/src/lib/generate_utils.ts +++ /dev/null @@ -1,574 +0,0 @@ -// @ts-ignore -import * as bls12377js from '@celo/bls12377js' -import { blsPrivateKeyToProcessedPrivateKey } from '@celo/cryptographic-utils/lib/bls' -import BigNumber from 'bignumber.js' -import { BIP32Factory, BIP32Interface } from 'bip32' -import * as bip39 from 'bip39' -import fs from 'fs' -import { merge, range, repeat } from 'lodash' -import { tmpdir } from 'os' -import path from 'path' -import * as rlp from 'rlp' // TODO(soloseng): update? -import { MyceloGenesisConfig } from 'src/lib/interfaces/mycelo-genesis-config' -import { CurrencyPair } from 'src/lib/k8s-oracle/base' -import * as ecc from 'tiny-secp256k1' -import Web3 from 'web3' -import { spawnCmd, spawnCmdWithExitOnFailure } from './cmd-utils' -import { envVar, fetchEnv, fetchEnvOrFallback, monorepoRoot } from './env-utils' -import { - CONTRACT_OWNER_STORAGE_LOCATION, - GENESIS_MSG_HASH, - GETH_CONFIG_OLD, - ISTANBUL_MIX_HASH, - REGISTRY_ADDRESS, - TEMPLATE, -} from './genesis_constants' -import { getIndexForLoadTestThread } from './geth' -import { GenesisConfig } from './interfaces/genesis-config' -import { ensure0x, strip0x } from './utils' - -const bip32 = BIP32Factory(ecc) - -export enum AccountType { - VALIDATOR = 0, - LOAD_TESTING_ACCOUNT = 1, - TX_NODE = 2, - BOOTNODE = 3, - FAUCET = 4, - ATTESTATION = 5, - PRICE_ORACLE = 6, - PROXY = 7, - ATTESTATION_BOT = 8, - VOTING_BOT = 9, - TX_NODE_PRIVATE = 10, - VALIDATOR_GROUP = 11, - ADMIN = 12, - TX_FEE_RECIPIENT = 13, -} - -export enum ConsensusType { - CLIQUE = 'clique', - ISTANBUL = 'istanbul', -} - -export interface Validator { - address: string - blsPublicKey: string - balance?: string -} - -export interface AccountAndBalance { - address: string - balance: string -} - -export const MNEMONIC_ACCOUNT_TYPE_CHOICES = [ - 'validator', - 'load_testing', - 'tx_node', - 'bootnode', - 'faucet', - 'attestation', - 'price_oracle', - 'proxy', - 'attestation_bot', - 'voting_bot', - 'tx_node_private', - 'validator_group', - 'admin', - 'tx_fee_recipient', -] - -export const add0x = (str: string) => { - return '0x' + str -} - -export const coerceMnemonicAccountType = (raw: string): AccountType => { - const index = MNEMONIC_ACCOUNT_TYPE_CHOICES.indexOf(raw) - if (index === -1) { - throw new Error('Invalid mnemonic account type') - } - return index -} - -export const generatePrivateKey = (mnemonic: string, accountType: AccountType, index: number) => { - return generatePrivateKeyWithDerivations(mnemonic, [accountType, index]) -} - -export const generateOraclePrivateKey = ( - mnemonic: string, - currencyPair: CurrencyPair, - index: number -) => { - let derivationPath: number[] - if (currencyPair === 'CELOUSD') { - // For backwards compatibility we don't add currencyPair to - // the derivation path for CELOUSD - derivationPath = [AccountType.PRICE_ORACLE, index] - } else { - // Deterministically convert the currency pair string to a path segment - // keccak(currencyPair) modulo 2^31 - const currencyDerivation = new BigNumber(Web3.utils.keccak256(currencyPair), 16) - .mod(2 ** 31) - .toNumber() - derivationPath = [AccountType.PRICE_ORACLE, currencyDerivation, index] - } - - return generatePrivateKeyWithDerivations(mnemonic, derivationPath) -} - -export const generatePrivateKeyWithDerivations = (mnemonic: string, derivations: number[]) => { - const seed = bip39.mnemonicToSeedSync(mnemonic) - const node = bip32.fromSeed(seed) - const newNode = derivations.reduce((n: BIP32Interface, derivation: number) => { - return n.derive(derivation) - }, node) - return newNode.privateKey!.toString('hex') -} - -export const generatePublicKey = (mnemonic: string, accountType: AccountType, index: number) => { - return privateKeyToPublicKey(generatePrivateKey(mnemonic, accountType, index)) -} - -export const generateAddress = (mnemonic: string, accountType: AccountType, index: number) => - privateKeyToAddress(generatePrivateKey(mnemonic, accountType, index)) - -export const privateKeyToPublicKey = (privateKey: string): string => { - // NOTE: elliptic is disabled elsewhere in this library to prevent - // accidental signing of truncated messages. - // tslint:disable-next-line:import-blacklist - const EC = require('elliptic').ec - const ec = new EC('secp256k1') - const ecPrivateKey = ec.keyFromPrivate(Buffer.from(privateKey, 'hex')) - const ecPublicKey: string = ecPrivateKey.getPublic('hex') - return ecPublicKey.slice(2) -} - -export const privateKeyToAddress = (privateKey: string) => { - // @ts-ignore - return new Web3.modules.Eth().accounts.privateKeyToAccount(ensure0x(privateKey)).address -} - -export const privateKeyToStrippedAddress = (privateKey: string) => - strip0x(privateKeyToAddress(privateKey)) - -const validatorZeroBalance = () => - fetchEnvOrFallback(envVar.VALIDATOR_ZERO_GENESIS_BALANCE, '103010030000000000000000000') // 103,010,030 CG -const validatorBalance = () => - fetchEnvOrFallback(envVar.VALIDATOR_GENESIS_BALANCE, '10011000000000000000000') // 10,011 CG -const faucetBalance = () => - fetchEnvOrFallback(envVar.FAUCET_GENESIS_BALANCE, '10011000000000000000000') // 10,011 CG -const oracleBalance = () => - fetchEnvOrFallback(envVar.MOCK_ORACLE_GENESIS_BALANCE, '100000000000000000000') // 100 CG -const votingBotBalance = () => - fetchEnvOrFallback(envVar.VOTING_BOT_BALANCE, '10000000000000000000000') // 10,000 CG - -export const getPrivateKeysFor = (accountType: AccountType, mnemonic: string, n: number) => - range(0, n).map((i) => generatePrivateKey(mnemonic, accountType, i)) - -export const getOraclePrivateKeysFor = (currencyPair: CurrencyPair, mnemonic: string, n: number) => - range(0, n).map((i) => generateOraclePrivateKey(mnemonic, currencyPair, i)) - -export const getAddressesFor = (accountType: AccountType, mnemonic: string, n: number) => - getPrivateKeysFor(accountType, mnemonic, n).map(privateKeyToAddress) - -export const getStrippedAddressesFor = (accountType: AccountType, mnemonic: string, n: number) => - getAddressesFor(accountType, mnemonic, n).map(strip0x) - -export const getValidatorsInformation = (mnemonic: string, n: number): Validator[] => { - return getPrivateKeysFor(AccountType.VALIDATOR, mnemonic, n).map((key, i) => { - const blsKeyBytes = blsPrivateKeyToProcessedPrivateKey(key) - return { - address: strip0x(privateKeyToAddress(key)), - blsPublicKey: bls12377js.BLS.privateToPublicBytes(blsKeyBytes).toString('hex'), - balance: i === 0 ? validatorZeroBalance() : validatorBalance(), - } - }) -} - -export const getAddressFromEnv = (accountType: AccountType, n: number) => { - const mnemonic = fetchEnv(envVar.MNEMONIC) - const privateKey = generatePrivateKey(mnemonic, accountType, n) - return privateKeyToAddress(privateKey) -} - -const getFaucetedAccountsFor = ( - accountType: AccountType, - mnemonic: string, - n: number, - balance: string -) => { - return getStrippedAddressesFor(accountType, mnemonic, n).map((address) => ({ - address, - balance, - })) -} - -const getFaucetedAccountsForLoadTest = ( - accountType: AccountType, - mnemonic: string, - clients: number, - threads: number, - balance: string -) => { - const addresses: string[] = [] - for (const podIndex of range(0, clients)) { - for (const threadIndex of range(0, threads)) { - const index = getIndexForLoadTestThread(podIndex, threadIndex) - addresses.push(strip0x(generateAddress(mnemonic, accountType, parseInt(`${index}`, 10)))) - } - } - return addresses.map((address) => ({ - address, - balance, - })) -} - -export const getFaucetedAccounts = (mnemonic: string) => { - const numFaucetAccounts = parseInt(fetchEnvOrFallback(envVar.FAUCET_GENESIS_ACCOUNTS, '0'), 10) - const faucetAccounts = getFaucetedAccountsFor( - AccountType.FAUCET, - mnemonic, - numFaucetAccounts, - faucetBalance() - ) - - const numLoadTestAccounts = parseInt(fetchEnvOrFallback(envVar.LOAD_TEST_CLIENTS, '0'), 10) - const numLoadTestThreads = parseInt(fetchEnvOrFallback(envVar.LOAD_TEST_THREADS, '0'), 10) - - const loadTestAccounts = getFaucetedAccountsForLoadTest( - AccountType.LOAD_TESTING_ACCOUNT, - mnemonic, - numLoadTestAccounts, - numLoadTestThreads, - faucetBalance() - ) - - const oracleAccounts = getFaucetedAccountsFor( - AccountType.PRICE_ORACLE, - mnemonic, - 1, - oracleBalance() - ) - - const numVotingBotAccounts = parseInt(fetchEnvOrFallback(envVar.VOTING_BOTS, '0'), 10) - const votingBotAccounts = getFaucetedAccountsFor( - AccountType.VOTING_BOT, - mnemonic, - numVotingBotAccounts, - votingBotBalance() - ) - - return [...faucetAccounts, ...loadTestAccounts, ...oracleAccounts, ...votingBotAccounts] -} - -const hardForkActivationBlock = (key: string) => { - const value = fetchEnvOrFallback(key, '') - if (value === '') { - return undefined - } else { - return parseInt(value, 10) - } -} - -export const generateGenesisFromEnv = (enablePetersburg: boolean = true) => { - const mnemonic = fetchEnv(envVar.MNEMONIC) - const validatorEnv = parseInt(fetchEnv(envVar.VALIDATORS), 10) - const genesisAccountsEnv = fetchEnvOrFallback(envVar.GENESIS_ACCOUNTS, '') - const validators = getValidatorsInformation(mnemonic, validatorEnv) - - const consensusType = fetchEnv(envVar.CONSENSUS_TYPE) as ConsensusType - - if (![ConsensusType.CLIQUE, ConsensusType.ISTANBUL].includes(consensusType)) { - console.error('Unsupported CONSENSUS_TYPE') - process.exit(1) - } - - const blockTime = parseInt(fetchEnv(envVar.BLOCK_TIME), 10) - const requestTimeout = parseInt( - fetchEnvOrFallback(envVar.ISTANBUL_REQUEST_TIMEOUT_MS, '3000'), - 10 - ) - const epoch = parseInt(fetchEnvOrFallback(envVar.EPOCH, '30000'), 10) - // allow 12 blocks in prod for the uptime metric - const lookbackwindow = parseInt(fetchEnvOrFallback(envVar.LOOKBACK, '12'), 10) - const chainId = parseInt(fetchEnv(envVar.NETWORK_ID), 10) - - const initialAccounts = getFaucetedAccounts(mnemonic) - if (genesisAccountsEnv !== '') { - const genesisAccountsPath = path.resolve(monorepoRoot, genesisAccountsEnv) - const genesisAccounts = JSON.parse(fs.readFileSync(genesisAccountsPath).toString()) - for (const addr of genesisAccounts.addresses) { - initialAccounts.push({ - address: addr, - balance: genesisAccounts.value, - }) - } - } - - // Allocate voting bot account(s) - const numVotingBotAccounts = parseInt(fetchEnvOrFallback(envVar.VOTING_BOTS, '0'), 10) - initialAccounts.concat( - getStrippedAddressesFor(AccountType.VOTING_BOT, mnemonic, numVotingBotAccounts).map((addr) => { - return { - address: addr, - balance: fetchEnvOrFallback(envVar.VOTING_BOT_BALANCE, '100000000000000000000'), - } - }) - ) - - // Celo hard fork activation blocks. Default is undefined, which means not activated. - const churritoBlock = hardForkActivationBlock(envVar.CHURRITO_BLOCK) - const donutBlock = hardForkActivationBlock(envVar.DONUT_BLOCK) - const espressoBlock = hardForkActivationBlock(envVar.ESPRESSO_BLOCK) - - // network start timestamp - const timestamp = parseInt(fetchEnvOrFallback(envVar.TIMESTAMP, '0'), 10) - - return generateGenesis({ - validators, - consensusType, - blockTime, - initialAccounts, - epoch, - lookbackwindow, - chainId, - requestTimeout, - enablePetersburg, - timestamp, - churritoBlock, - donutBlock, - espressoBlock, - }) -} - -export const generateIstanbulExtraData = (validators: Validator[]) => { - const istanbulVanity = GENESIS_MSG_HASH - // Vanity prefix is 32 bytes (1 hex char/.5 bytes * 32 bytes = 64 hex chars) - if (istanbulVanity.length !== 32 * 2) { - throw new Error('Istanbul vanity must be 32 bytes') - } - const blsSignatureVanity = 96 - const ecdsaSignatureVanity = 65 - return ( - '0x' + - istanbulVanity + - rlp - // @ts-ignore - .encode([ - // Added validators - validators.map((validator) => Buffer.from(validator.address, 'hex')), - validators.map((validator) => Buffer.from(validator.blsPublicKey, 'hex')), - // Removed validators - Buffer.alloc(0), - // Seal - Buffer.from(repeat('0', ecdsaSignatureVanity * 2), 'hex'), - [ - // AggregatedSeal.Bitmap - Buffer.alloc(0), - // AggregatedSeal.Signature - Buffer.from(repeat('0', blsSignatureVanity * 2), 'hex'), - // AggregatedSeal.Round - Buffer.alloc(0), - ], - [ - // ParentAggregatedSeal.Bitmap - Buffer.alloc(0), - // ParentAggregatedSeal.Signature - Buffer.from(repeat('0', blsSignatureVanity * 2), 'hex'), - // ParentAggregatedSeal.Round - Buffer.alloc(0), - ], - ]) - .toString('hex') - ) -} - -export const generateGenesis = ({ - validators, - consensusType = ConsensusType.ISTANBUL, - initialAccounts: otherAccounts = [], - blockTime, - epoch, - lookbackwindow, - chainId, - requestTimeout, - enablePetersburg = true, - timestamp = 0, - churritoBlock, - donutBlock, - espressoBlock, - gingerbreadBlock, -}: GenesisConfig): string => { - const genesis: any = { ...TEMPLATE } - - if (!enablePetersburg) { - genesis.config = GETH_CONFIG_OLD - } - - if (typeof churritoBlock === 'number') { - genesis.config.churritoBlock = churritoBlock - } - if (typeof donutBlock === 'number') { - genesis.config.donutBlock = donutBlock - } - if (typeof espressoBlock === 'number') { - genesis.config.espressoBlock = espressoBlock - } - if (typeof gingerbreadBlock === 'number') { - genesis.config.gingerbreadBlock = gingerbreadBlock - } - - genesis.config.chainId = chainId - - if (consensusType === ConsensusType.CLIQUE) { - genesis.config.clique = { - period: blockTime, - epoch, - } - } else if (consensusType === ConsensusType.ISTANBUL) { - genesis.mixHash = ISTANBUL_MIX_HASH - genesis.difficulty = '0x1' - if (validators) { - genesis.extraData = generateIstanbulExtraData(validators) - } - genesis.config.istanbul = { - // see github.com/celo-org/celo-blockchain/blob/master/consensus/istanbul/config.go#L21-L25 - // 0 = RoundRobin, 1 = Sticky, 2 = ShuffledRoundRobin - policy: 2, - blockperiod: blockTime, - requesttimeout: requestTimeout, - epoch, - lookbackwindow, - } - } - - if (validators) { - for (const validator of validators) { - genesis.alloc[validator.address] = { - balance: validator.balance, - } - } - } - - for (const account of otherAccounts) { - genesis.alloc[account.address] = { - balance: account.balance, - } - } - - const contracts = [REGISTRY_ADDRESS] - const contractBuildPath = path.resolve( - monorepoRoot, - 'packages/protocol/build/contracts/Proxy.json' - ) - - if (validators && validators.length > 0) { - for (const contract of contracts) { - genesis.alloc[contract] = { - code: JSON.parse(fs.readFileSync(contractBuildPath).toString()).deployedBytecode, - storage: { - [CONTRACT_OWNER_STORAGE_LOCATION]: validators[0].address, - }, - balance: '0', - } - } - } - - genesis.timestamp = timestamp > 0 ? timestamp.toString() : '0x0' - - return JSON.stringify(genesis, null, 2) -} - -// This function assumes that mycelo has already been built using 'make all' -export const generateGenesisWithMigrations = async ({ - gethRepoPath, - genesisConfig, - mnemonic, - numValidators, - verbose, -}: MyceloGenesisConfig): Promise => { - const tmpDir = path.join(tmpdir(), `mycelo-genesis-${Date.now()}`) - fs.mkdirSync(tmpDir) - const envFile = path.join(tmpDir, 'env.json') - const configFile = path.join(tmpDir, 'genesis-config.json') - const myceloBinaryPath = path.join(gethRepoPath!, '/build/bin/mycelo') - await spawnCmdWithExitOnFailure( - myceloBinaryPath, - [ - 'genesis-config', - '--template', - 'monorepo', - '--mnemonic', - mnemonic, - '--validators', - numValidators.toString(), - ], - { - silent: !verbose, - cwd: tmpDir, - } - ) - const mcEnv = JSON.parse(fs.readFileSync(envFile).toString()) - const mcConfig = JSON.parse(fs.readFileSync(configFile).toString()) - - // Customize and overwrite the env.json file - merge(mcEnv, { - chainId: genesisConfig.chainId, - accounts: { - validators: numValidators, - }, - }) - fs.writeFileSync(envFile, JSON.stringify(mcEnv, undefined, 2)) - - // Customize and overwrite the genesis-config.json file - if (genesisConfig.chainId) { - mcConfig.chainId = genesisConfig.chainId - } - if (genesisConfig.epoch) { - mcConfig.istanbul.epoch = genesisConfig.epoch - } - if (genesisConfig.lookbackwindow) { - mcConfig.istanbul.lookbackwindow = genesisConfig.lookbackwindow - } - if (genesisConfig.blockTime) { - mcConfig.istanbul.blockperiod = genesisConfig.blockTime - } - if (genesisConfig.requestTimeout) { - mcConfig.istanbul.requesttimeout = genesisConfig.requestTimeout - } - if (genesisConfig.churritoBlock !== undefined) { - mcConfig.hardforks.churritoBlock = genesisConfig.churritoBlock - } - if (genesisConfig.donutBlock !== undefined) { - mcConfig.hardforks.donutBlock = genesisConfig.donutBlock - } - if (genesisConfig.espressoBlock !== undefined) { - mcConfig.hardforks.espressoBlock = genesisConfig.espressoBlock - } - if (genesisConfig.gingerbreadBlock !== undefined) { - mcConfig.hardforks.gingerbreadBlock = genesisConfig.gingerbreadBlock - } - if (genesisConfig.timestamp !== undefined) { - mcConfig.genesisTimestamp = genesisConfig.timestamp - } - - // TODO: overrides for migrations - - fs.writeFileSync(configFile, JSON.stringify(mcConfig, undefined, 2)) - - // Generate the genesis file, and return its contents - const contractsBuildPath = path.resolve(monorepoRoot, 'packages/protocol/build/contracts/') - await spawnCmdWithExitOnFailure( - myceloBinaryPath, - ['genesis-from-config', tmpDir, '--buildpath', contractsBuildPath], - { - silent: !verbose, - cwd: tmpDir, - } - ) - const genesis = fs.readFileSync(path.join(tmpDir, 'genesis.json')).toString() - // Clean up the tmp dir as it's no longer needed - await spawnCmd('rm', ['-rf', tmpDir], { silent: true }) - return genesis -} diff --git a/packages/celotool/src/lib/genesis_constants.ts b/packages/celotool/src/lib/genesis_constants.ts deleted file mode 100644 index d1e67ddca..000000000 --- a/packages/celotool/src/lib/genesis_constants.ts +++ /dev/null @@ -1,45 +0,0 @@ -export const GETH_CONFIG_OLD = { - chainId: 1101, - homesteadBlock: 1, - eip150Block: 2, - eip150Hash: '0x0000000000000000000000000000000000000000000000000000000000000000', - eip155Block: 3, - eip158Block: 3, - byzantiumBlock: 4, -} - -export const TEMPLATE = { - config: { - homesteadBlock: 0, - eip150Block: 0, - eip150Hash: '0x0000000000000000000000000000000000000000000000000000000000000000', - eip155Block: 0, - eip158Block: 0, - byzantiumBlock: 0, - constantinopleBlock: 0, - petersburgBlock: 0, - istanbulBlock: 0, - }, - nonce: '0x0', - timestamp: '0x5b843511', - gasLimit: '0x8000000', - extraData: - '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000feE1a22F43BeeCB912B5a4912ba87527682ef0fC889F21CE69dcc25a4594f73230A55896d67038065372d2bbBaBaAf1495182E31cF13dB0d18463B0EF71690ea7E0c67827d8968882FAC0c4cBBD65BCE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - difficulty: '0x0400', - coinbase: '0x0000000000000000000000000000000000000000', - alloc: {}, - number: '0x0', - gasUsed: '0x0', - mixHash: '0x0000000000000000000000000000000000000000000000000000000000000000', - parentHash: '0x0000000000000000000000000000000000000000000000000000000000000000', -} - -export const REGISTRY_ADDRESS = '000000000000000000000000000000000000ce10' - -export const CONTRACT_OWNER_STORAGE_LOCATION = - '0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103' -export const ISTANBUL_MIX_HASH = - '0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365' - -// Keccak256 of "The Times 09/Apr/2020 With $2.3 Trillion Injection, Fed’s Plan Far Exceeds Its 2008 Rescue" -export const GENESIS_MSG_HASH = 'ecc833a7747eaa8327335e8e0c6b6d8aa3a38d0063591e43ce116ccf5c89753e' diff --git a/packages/celotool/src/lib/geth.ts b/packages/celotool/src/lib/geth.ts deleted file mode 100644 index 90d76e186..000000000 --- a/packages/celotool/src/lib/geth.ts +++ /dev/null @@ -1,1565 +0,0 @@ -// tslint:disable:no-console -import { CeloTxReceipt, TransactionResult } from '@celo/connect' -import { CeloContract, ContractKit, newKitFromWeb3 } from '@celo/contractkit' -import { GoldTokenWrapper } from '@celo/contractkit/lib/wrappers/GoldTokenWrapper' -import { StableTokenWrapper } from '@celo/contractkit/lib/wrappers/StableTokenWrapper' -import { waitForPortOpen } from '@celo/dev-utils/lib/network' -import BigNumber from 'bignumber.js' -import { spawn } from 'child_process' -import { randomBytes } from 'crypto' -import fs from 'fs' -import { merge, range } from 'lodash' -import fetch from 'node-fetch' -import path from 'path' -import sleep from 'sleep-promise' -import Web3 from 'web3' -import { Admin } from 'web3-eth-admin' -import { spawnCmd, spawnCmdWithExitOnFailure } from './cmd-utils' -import { convertToContractDecimals } from './contract-utils' -import { envVar, fetchEnv, fetchEnvOrFallback } from './env-utils' -import { - AccountType, - generateGenesis, - generateGenesisWithMigrations, - generatePrivateKey, - privateKeyToAddress, - privateKeyToPublicKey, - Validator, -} from './generate_utils' -import { retrieveClusterIPAddress, retrieveIPAddress } from './helm_deploy' -import { GethInstanceConfig } from './interfaces/geth-instance-config' -import { GethRunConfig } from './interfaces/geth-run-config' -import { ensure0x } from './utils' - -export async function unlockAccount( - web3: Web3, - duration: number, - password: string, - accountAddress: string | null = null -) { - if (accountAddress === null) { - const accounts = await web3.eth.getAccounts() - accountAddress = accounts[0] - } - await web3.eth.personal.unlockAccount(accountAddress!, password, duration) - return accountAddress! -} - -type HandleErrorCallback = (isError: boolean, data: { location: string; error: string }) => void - -const DEFAULT_TRANSFER_AMOUNT = new BigNumber('0.00000000000001') -const LOAD_TEST_TRANSFER_WEI = new BigNumber(10000) - -const GETH_IPC = 'geth.ipc' -const DISCOVERY_PORT = 30303 -const BOOTNODE_DISCOVERY_PORT = 30301 - -const BLOCKSCOUT_TIMEOUT = 12000 // ~ 12 seconds needed to see the transaction in the blockscout - -// for log messages which indicate that blockscout where not able to provide -// information about transaction in a "timely" (15s for now) manner -export const LOG_TAG_BLOCKSCOUT_TIMEOUT = 'blockscout_timeout' -// for log messages which show time (+- 150-200ms) needed for blockscout to -// fetch and publish information about transaction -export const LOG_TAG_BLOCKSCOUT_TIME_MEASUREMENT = 'blockscout_time_measurement' -// for log messages which show the error about validating transaction receipt -export const LOG_TAG_BLOCKSCOUT_VALIDATION_ERROR = 'validate_blockscout_error' -// for log messages which show the error occurred when fetching a contract address -export const LOG_TAG_CONTRACT_ADDRESS_ERROR = 'contract_address_error' -// for log messages which show the error while validating geth rpc response -export const LOG_TAG_GETH_RPC_ERROR = 'geth_rpc_error' -// for log messages which show the error occurred when the transaction has -// been sent -export const LOG_TAG_TRANSACTION_ERROR = 'transaction_error' -// message indicating that the tx hash has been received in callback within sendTransaction -export const LOG_TAG_TRANSACTION_HASH_RECEIVED = 'tx_hash_received' -// for log messages which show the error about validating transaction receipt -export const LOG_TAG_TRANSACTION_VALIDATION_ERROR = 'validate_transaction_error' -// for log messages which show time needed to receive the receipt after -// the transaction has been sent -export const LOG_TAG_TX_TIME_MEASUREMENT = 'tx_time_measurement' -// max number of threads used for load testing -export const MAX_LOADTEST_THREAD_COUNT = 100 - -export const getEnodeAddress = (nodeId: string, ipAddress: string, port: number) => { - return `enode://${nodeId}@${ipAddress}:${port}` -} - -export const getBootnodeEnode = async (namespace: string) => { - const ip = await retrieveBootnodeIPAddress(namespace) - const privateKey = generatePrivateKey(fetchEnv(envVar.MNEMONIC), AccountType.BOOTNODE, 0) - const nodeId = privateKeyToPublicKey(privateKey) - return [getEnodeAddress(nodeId, ip, BOOTNODE_DISCOVERY_PORT)] -} - -export const retrieveBootnodeIPAddress = async (namespace: string) => { - // Baklava bootnode address comes from VM and has an different name (not possible to update name after creation) - const resourceName = - namespace === 'baklava' ? `${namespace}-bootnode-address` : `${namespace}-bootnode` - if (fetchEnv(envVar.STATIC_IPS_FOR_GETH_NODES) === 'true') { - return retrieveIPAddress(resourceName) - } else { - return retrieveClusterIPAddress('service', resourceName, namespace) - } -} - -const retrieveTxNodeAddresses = async (namespace: string, txNodesNum: number) => { - const txNodesRange = range(0, txNodesNum) - return Promise.all(txNodesRange.map((i) => retrieveIPAddress(`${namespace}-tx-nodes-${i}`))) -} - -const getEnodesWithIpAddresses = async (namespace: string, getExternalIP: boolean) => { - const txNodesNum = parseInt(fetchEnv(envVar.TX_NODES), 10) - const txAddresses = await retrieveTxNodeAddresses(namespace, txNodesNum) - const txNodesRange = range(0, txNodesNum) - return Promise.all( - txNodesRange.map(async (index) => { - const privateKey = generatePrivateKey(fetchEnv(envVar.MNEMONIC), AccountType.TX_NODE, index) - const nodeId = privateKeyToPublicKey(privateKey) - let address: string - if (getExternalIP) { - address = txAddresses[index] - } else { - address = await retrieveClusterIPAddress( - 'service', - `${namespace}-service-${index}`, - namespace - ) - if (address.length === 0) { - console.error('IP address is empty for transaction node') - throw new Error('IP address is empty for transaction node') - } - } - return getEnodeAddress(nodeId, address, DISCOVERY_PORT) - }) - ) -} - -export const getEnodesAddresses = async (namespace: string) => { - return getEnodesWithIpAddresses(namespace, false) -} - -export const getEnodesWithExternalIPAddresses = async (namespace: string) => { - return getEnodesWithIpAddresses(namespace, true) -} - -export function getPrivateTxNodeClusterIP(celoEnv: string) { - return retrieveClusterIPAddress('service', 'tx-nodes-private', celoEnv) -} - -export const fetchPassword = (passwordFile: string) => { - if (!fs.existsSync(passwordFile)) { - console.error(`Password file at ${passwordFile} does not exists!`) - process.exit(1) - } - return fs.readFileSync(passwordFile).toString() -} - -export const writeStaticNodes = ( - enodes: string[], - outputDirPath: string, - outputFileName: string, - spacing: number = 2 -) => { - const encodedJSON = JSON.stringify(enodes, null, spacing) - - fs.writeFile(path.join(outputDirPath, outputFileName), encodedJSON, (err) => { - if (err) { - console.error(err) - process.exit(1) - } - }) -} - -export const checkGethStarted = (dataDir: string) => { - if (!fs.existsSync(path.resolve(dataDir, GETH_IPC))) { - console.error(`Looks like there are no local geth nodes running in ${dataDir}`) - console.info( - `Please, make sure you specified correct data directory, you could also run the geth node by "celotooljs geth run"` - ) - process.exit(1) - } -} - -export const getWeb3AndTokensContracts = async () => { - const kit = newKitFromWeb3(new Web3('http://localhost:8545')) - const [goldToken, stableToken] = await Promise.all([ - kit.contracts.getGoldToken(), - kit.contracts.getStableToken(), - ]) - - return { - kit, - goldToken, - stableToken, - } -} - -export const getRandomInt = (from: number, to: number) => { - return Math.floor(Math.random() * (to - from)) + from -} - -const getRandomToken = (goldToken: GoldTokenWrapper, stableToken: StableTokenWrapper) => { - const tokenType = getRandomInt(0, 2) - if (tokenType === 0) { - return goldToken - } else { - return stableToken - } -} - -const validateGethRPC = async ( - kit: ContractKit, - txHash: string, - from: string, - handleError: HandleErrorCallback -) => { - const transaction = await kit.connection.getTransaction(txHash) - handleError(!transaction || !transaction.from, { - location: '[GethRPC]', - error: `Contractkit did not return a valid transaction`, - }) - if (transaction == null) { - return - } - const txFrom = transaction.from.toLowerCase() - const expectedFrom = from.toLowerCase() - handleError(!transaction.from || expectedFrom !== txFrom, { - location: '[GethRPC]', - error: `Expected "from" to equal ${expectedFrom}, but found ${txFrom}`, - }) -} - -const checkBlockscoutResponse = ( - json: any /* response */, - txHash: string, - from: string, - handleError: HandleErrorCallback -) => { - const location = '[Blockscout]' - - handleError(json.status !== '1', { location, error: `Invalid status: expected '1', received` }) - handleError(!json.result, { location, error: `No result found: receive ${json.status.result}` }) - const resultFrom = json.result.from.toLowerCase() - const expectedFrom = from.toLowerCase() - handleError(resultFrom !== expectedFrom, { - location, - error: `Expected "from" to equal ${expectedFrom}, but found ${resultFrom}`, - }) - handleError(json.result.hash !== txHash, { - location, - error: `Expected "hash" to equal ${txHash}, but found ${json.result.hash}`, - }) -} - -const fetchBlockscoutTxInfo = async (url: string, txHash: string) => { - const response = await fetch(`${url}/api?module=transaction&action=gettxinfo&txhash=${txHash}`) - return response.json() as any -} - -const validateBlockscout = async ( - url: string, - txHash: string, - from: string, - handleError: HandleErrorCallback -) => { - const json = await fetchBlockscoutTxInfo(url, txHash) - - checkBlockscoutResponse(json, txHash, from, handleError) -} - -// Maximal time given for blockscout to provide info about tx -// If the transaction does not appear in blockscout within 15 seconds, -// blockscout is considered to be not working in a timely manner -const MAXIMAL_BLOCKSCOUT_TIMEOUT = 15000 - -// Try to fetch info about transaction every 150 ms -const BLOCKSCOUT_FETCH_RETRY_TIME = 150 - -// within MAXIMAL_BLOCKSCOUT_TIMEOUT ms -const getFirstValidBlockscoutResponse = async (url: string, txHash: string) => { - const attempts = MAXIMAL_BLOCKSCOUT_TIMEOUT / BLOCKSCOUT_FETCH_RETRY_TIME - for (let attemptId = 0; attemptId < attempts; attemptId++) { - const json = await fetchBlockscoutTxInfo(url, txHash) - if (json.status !== '1') { - await sleep(BLOCKSCOUT_FETCH_RETRY_TIME) - } else { - return [json, Date.now()] - } - } - return [null, null] -} - -const validateTransactionAndReceipt = ( - from: string, - txReceipt: any, - handleError: HandleErrorCallback -) => { - const location = '[TX & Receipt]' - - handleError(!txReceipt, { location, error: 'No transaction receipt received!' }) - handleError(txReceipt.status !== true, { - location, - error: `Transaction receipt status (${txReceipt.status}) is not true!`, - }) - handleError(txReceipt.from.toLowerCase() !== from.toLowerCase(), { - location, - error: `Transaction receipt from (${txReceipt.from}) is not equal to sender address (${from}).`, - }) -} - -const tracerLog = (logMessage: any) => { - console.log(JSON.stringify(logMessage)) -} - -const exitTracerTool = (logMessage: any) => { - tracerLog(logMessage) - process.exit(1) -} - -const transferAndTrace = async ( - kit: ContractKit, - goldToken: GoldTokenWrapper, - stableToken: StableTokenWrapper, - from: string, - to: string, - password: string, - blockscoutUrl: string -) => { - console.info('Transfer') - - const token = getRandomToken(goldToken, stableToken) - const feeCurrencyToken = getRandomToken(goldToken, stableToken) - - const [tokenName, feeCurrencySymbol] = await Promise.all([ - token.symbol(), - feeCurrencyToken.symbol(), - ]) - - const logMessage: any = { - severity: 'CRITICAL', - senderAddress: from, - receiverAddress: to, - blockscout: blockscoutUrl, - token: tokenName, - error: '', - location: '', - txHash: '', - } - - const txParams: any = {} - // Fill txParams below - if (getRandomInt(0, 2) === 3) { - txParams.feeCurrency = feeCurrencyToken.address - logMessage.feeCurrency = feeCurrencySymbol - } - - const transferToken = new Promise(async (resolve) => { - await transferERC20Token( - kit, - token, - from, - to, - DEFAULT_TRANSFER_AMOUNT, - password, - txParams, - undefined, - (receipt: any) => { - resolve(receipt) - }, - (error: any) => { - logMessage.error = error - exitTracerTool(logMessage) - } - ) - }) - - const txReceipt: any = await transferToken - const txHash = txReceipt ? txReceipt.transactionHash : '' - - // Need to wait for a bit to make sure that blockscout had enough time - // to see the transaction and display it - await sleep(BLOCKSCOUT_TIMEOUT) - - logMessage.txHash = txHash - - const handleError = (isError: boolean, data: { location: string; error: string }) => { - if (isError) { - exitTracerTool({ ...logMessage, ...data }) - } - } - - validateTransactionAndReceipt(from, txReceipt!, handleError) - await validateBlockscout(blockscoutUrl, txHash, from, handleError) - await validateGethRPC(kit, txHash, from, handleError) -} - -export const traceTransactions = async ( - kit: ContractKit, - goldToken: GoldTokenWrapper, - stableToken: StableTokenWrapper, - addresses: string[], - blockscoutUrl: string -) => { - console.info('Starting simulation') - - await transferAndTrace(kit, goldToken, stableToken, addresses[0], addresses[1], '', blockscoutUrl) - - await transferAndTrace(kit, goldToken, stableToken, addresses[1], addresses[0], '', blockscoutUrl) - - console.info('Simulation finished successully!') -} - -const measureBlockscout = async ( - blockscoutUrl: string, - txHash: string, - from: string, - obtainReceiptTime: number, - baseLogMessage: any -) => { - const [json, receivedTime] = await getFirstValidBlockscoutResponse(blockscoutUrl, txHash) - if (receivedTime === null) { - tracerLog({ - tag: LOG_TAG_BLOCKSCOUT_TIMEOUT, - ...baseLogMessage, - }) - } else { - tracerLog({ - tag: LOG_TAG_BLOCKSCOUT_TIME_MEASUREMENT, - p_time: receivedTime - obtainReceiptTime, - ...baseLogMessage, - }) - checkBlockscoutResponse(json, txHash, from, (isError, data) => { - if (isError) { - tracerLog({ - tag: LOG_TAG_BLOCKSCOUT_VALIDATION_ERROR, - ...data, - ...baseLogMessage, - }) - } - }) - } -} - -export const transferCalldata = async ( - kit: ContractKit, - fromAddress: string, - toAddress: string, - amount: BigNumber, - dataStr?: string, - txOptions: { - gas?: number - gasPrice?: string - feeCurrency?: string - gatewayFeeRecipient?: string - gatewayFee?: string - nonce?: number - } = {} -) => { - return kit.sendTransaction({ - from: fromAddress, - to: toAddress, - value: amount.toString(), - data: dataStr, - gas: txOptions.gas, - gasPrice: txOptions.gasPrice, - gatewayFeeRecipient: txOptions.gatewayFeeRecipient, - gatewayFee: txOptions.gatewayFee, - nonce: txOptions.nonce, - }) -} - -export const transferCeloGold = async ( - kit: ContractKit, - fromAddress: string, - toAddress: string, - amount: BigNumber, - _?: string, - txOptions: { - gas?: number - gasPrice?: string - feeCurrency?: string - gatewayFeeRecipient?: string - gatewayFee?: string - nonce?: number - } = {} -) => { - const kitGoldToken = await kit.contracts.getGoldToken() - return kitGoldToken.transfer(toAddress, amount.toString()).send({ - from: fromAddress, - gas: txOptions.gas, - gasPrice: txOptions.gasPrice, - feeCurrency: txOptions.feeCurrency || undefined, - gatewayFeeRecipient: txOptions.gatewayFeeRecipient, - gatewayFee: txOptions.gatewayFee, - nonce: txOptions.nonce, - }) -} - -export const transferCeloDollars = async ( - kit: ContractKit, - fromAddress: string, - toAddress: string, - amount: BigNumber, - _?: string, - txOptions: { - gas?: number - gasPrice?: string - feeCurrency?: string - gatewayFeeRecipient?: string - gatewayFee?: string - nonce?: number - } = {} -) => { - const kitStableToken = await kit.contracts.getStableToken() - return kitStableToken.transfer(toAddress, amount.toString()).send({ - from: fromAddress, - gas: txOptions.gas, - gasPrice: txOptions.gasPrice, - feeCurrency: txOptions.feeCurrency || undefined, - gatewayFeeRecipient: txOptions.gatewayFeeRecipient, - gatewayFee: txOptions.gatewayFee, - nonce: txOptions.nonce, - }) -} - -export const unlock = async ( - kit: ContractKit, - address: string, - password: string, - unlockPeriod: number -) => { - try { - await kit.web3.eth.personal.unlockAccount(address, password, unlockPeriod) - } catch (error) { - console.error(`Unlock account ${address} failed:`, error) - } -} - -export enum TestMode { - Mixed = 'mixed', - Data = 'data', - Transfer = 'transfer', - StableTransfer = 'stable_transfer', - ContractCall = 'contract_call', -} - -export const simulateClient = async ( - senderPK: string, - recipientAddress: string, - contractAddress: string, - contractData: string, - txPeriodMs: number, // time between new transactions in ms - blockscoutUrl: string, - blockscoutMeasurePercent: number, // percent of time in range [0, 100] to measure blockscout for a tx - index: number, - testMode: TestMode, - thread: number, - maxGasPrice: BigNumber = new BigNumber(0), - totalTxGas: number = 500000, // aim for half million gas txs - web3Provider: string = 'http://127.0.0.1:8545' -) => { - // Assume the node is accessible via localhost with senderAddress unlocked - const kit = newKitFromWeb3(new Web3(web3Provider)) - - let lastNonce: number = -1 - let lastTx: string = '' - let lastGasPriceMinimum: BigNumber = new BigNumber(0) - let nonce: number = 0 - let recipientAddressFinal: string = recipientAddress - const useRandomRecipient = fetchEnvOrFallback(envVar.LOAD_TEST_USE_RANDOM_RECIPIENT, 'false') - - kit.connection.addAccount(senderPK) - kit.defaultAccount = privateKeyToAddress(senderPK) - - const sleepTime = 5000 - while (await kit.connection.isSyncing()) { - console.info( - `LoadTestId ${index} waiting for web3Provider to be synced. Sleeping ${sleepTime}ms` - ) - await sleep(sleepTime) - } - - // sleep a random amount of time in the range [0, txPeriodMs) before starting so - // that if multiple simulations are started at the same time, they don't all - // submit transactions at the same time - const randomSleep = Math.random() * txPeriodMs - console.info(`Sleeping for ${randomSleep} ms`) - await sleep(randomSleep) - - const txConf = await getTxConf(testMode) - const intrinsicGas = txConf.feeCurrencyGold ? 21000 : 71000 - const calldataGas = totalTxGas - intrinsicGas - const calldataSize = calldataGas / 4 // 119750 < tx pool size limit (128k) - let dataStr = testMode === TestMode.Data ? getBigData(calldataSize) : undefined // aim for half million gas txs - // Also running below the 128kb limit from the tx pool - let transferAmount = LOAD_TEST_TRANSFER_WEI - - if (testMode === TestMode.ContractCall) { - if (!contractData || !contractAddress) { - throw new Error('Contract address and data must be provided for TestMode.ContractCall') - } - dataStr = contractData - recipientAddressFinal = contractAddress - transferAmount = new BigNumber(0) - } - - const baseLogMessage: any = { - loadTestID: index, - threadID: thread, - sender: kit.defaultAccount, - recipient: recipientAddressFinal, - feeCurrency: '', - txHash: '', - tokenName: txConf.tokenName, - } - - while (true) { - const sendTransactionTime = Date.now() - - // randomly choose the recipientAddress if configured - if (useRandomRecipient === 'true') { - recipientAddressFinal = `0x${randomBytes(20).toString('hex')}` - baseLogMessage.recipient = recipientAddressFinal - } - - let txOptions - const feeCurrency = await getFeeCurrency(kit, txConf.feeCurrencyGold, baseLogMessage) - - baseLogMessage.feeCurrency = feeCurrency - try { - let gasPrice = await getGasPrice(kit, feeCurrency) - - // Check if last tx was mined. If not, reuse the same nonce - const nonceResult = await getNonce( - kit, - kit.defaultAccount, - lastTx, - lastNonce, - gasPrice, - lastGasPriceMinimum - ) - nonce = nonceResult.nonce - gasPrice = nonceResult.newPrice - if (maxGasPrice.isGreaterThan(0)) { - gasPrice = BigNumber.min(gasPrice, maxGasPrice) - } - lastGasPriceMinimum = gasPrice - txOptions = { - gasPrice: gasPrice.toString(), - feeCurrency, - nonce, - } - } catch (error: any) { - tracerLog({ - tag: LOG_TAG_CONTRACT_ADDRESS_ERROR, - error: error.toString(), - ...baseLogMessage, - }) - } - - if (testMode === TestMode.ContractCall) { - if (!contractData || !contractAddress) { - throw new Error('Contract address and data must be provided for TestMode.ContractCall') - } - dataStr = contractData - recipientAddressFinal = contractAddress - } - - await txConf - .transferFn( - kit, - kit.defaultAccount, - recipientAddressFinal, - transferAmount, - dataStr, - txOptions - ) - .then(async (txResult: TransactionResult) => { - lastTx = await txResult.getHash() - lastNonce = (await kit.web3.eth.getTransaction(lastTx)).nonce - await onLoadTestTxResult( - kit, - kit.defaultAccount!, - txResult, - sendTransactionTime, - baseLogMessage, - blockscoutUrl, - blockscoutMeasurePercent - ) - }) - .catch((error: any) => { - tracerLog({ - tag: LOG_TAG_TRANSACTION_ERROR, - error: error.toString(), - ...baseLogMessage, - }) - }) - if (sendTransactionTime + txPeriodMs > Date.now()) { - await sleep(sendTransactionTime + txPeriodMs - Date.now()) - } - } -} - -const getBigData = (size: number) => { - return '0x' + '00'.repeat(size) -} - -const getTxConf = async (testMode: TestMode) => { - switch (testMode) { - case TestMode.Data: - return { - feeCurrencyGold: true, - tokenName: 'cGLD.L', - transferFn: transferCalldata, - } - case TestMode.Transfer: - return { - feeCurrencyGold: true, - tokenName: 'cGLD', - transferFn: transferCeloGold, - } - case TestMode.StableTransfer: - return { - feeCurrencyGold: false, - tokenName: 'cUSD', - transferFn: transferCeloDollars, - } - case TestMode.Mixed: - // randomly choose which token to use - const useGold = Boolean(Math.round(Math.random())) - const _transferFn = useGold ? transferCeloGold : transferCeloDollars - const _tokenName = useGold ? 'cGLD' : 'cUSD' - - // randomly choose which gas currency to use - const _feeCurrencyGold = Boolean(Math.round(Math.random())) - return { - feeCurrencyGold: _feeCurrencyGold, - tokenName: _tokenName, - transferFn: _transferFn, - } - case TestMode.ContractCall: - return { - feeCurrencyGold: true, - tokenName: 'contract', // For logging - transferFn: transferCalldata, - } - default: - throw new Error(`Unimplemented TestMode: ${testMode}`) - } -} - -const getNonce = async ( - kit: ContractKit, - senderAddress: string, - lastTx: any, - lastNonce: any, - gasPrice: BigNumber, - lastGasPriceMinimum: BigNumber -) => { - let _nonce, _newPrice - _newPrice = gasPrice - if (lastTx === '' || lastNonce === -1) { - _nonce = await kit.web3.eth.getTransactionCount(senderAddress, 'latest') - } else if ((await kit.connection.getTransactionReceipt(lastTx))?.blockNumber) { - _nonce = await kit.web3.eth.getTransactionCount(senderAddress, 'latest') - } else { - _nonce = (await kit.web3.eth.getTransactionCount(senderAddress, 'latest')) - 1 - _newPrice = BigNumber.max(gasPrice.toNumber(), lastGasPriceMinimum.times(1.02)).dp(0) - console.warn( - `TX ${lastTx} was not mined. Replacing tx reusing nonce ${_nonce} and gasPrice ${_newPrice}` - ) - } - return { - newPrice: _newPrice, - nonce: _nonce, - } -} - -const getFeeCurrency = async (kit: ContractKit, feeCurrencyGold: boolean, baseLogMessage: any) => { - try { - return feeCurrencyGold ? '' : await kit.registry.addressFor(CeloContract.StableToken) - } catch (error: any) { - tracerLog({ - tag: LOG_TAG_CONTRACT_ADDRESS_ERROR, - error: error.toString(), - ...baseLogMessage, - }) - } -} - -const getGasPrice = async (kit: ContractKit, feeCurrency?: string) => { - const gasPriceMinimum = await kit.contracts.getGasPriceMinimum() - const gasPriceBase = feeCurrency - ? await gasPriceMinimum.getGasPriceMinimum(feeCurrency) - : await gasPriceMinimum.gasPriceMinimum() - return new BigNumber(gasPriceBase).times(2).dp(0) -} - -export const onLoadTestTxResult = async ( - kit: ContractKit, - senderAddress: string, - txResult: TransactionResult, - sendTransactionTime: number, - baseLogMessage: any, - blockscoutUrl: string, - blockscoutMeasurePercent: number -) => { - const txReceipt = await txResult.waitReceipt() - const txHash = txReceipt.transactionHash - baseLogMessage.txHash = txHash - - const receiptTime = Date.now() - - tracerLog({ - tag: LOG_TAG_TX_TIME_MEASUREMENT, - p_time: receiptTime - sendTransactionTime, - ...baseLogMessage, - }) - // Continuing only with receipt received - validateTransactionAndReceipt(senderAddress, txReceipt, (isError, data) => { - if (isError) { - tracerLog({ - tag: LOG_TAG_TRANSACTION_VALIDATION_ERROR, - ...baseLogMessage, - ...data, - }) - } - }) - - if (Math.random() * 100 < blockscoutMeasurePercent) { - await measureBlockscout( - blockscoutUrl, - txReceipt.transactionHash, - senderAddress, - receiptTime, - baseLogMessage - ) - } - - await validateGethRPC(kit, txHash, senderAddress, (isError, data) => { - if (isError) { - tracerLog({ - tag: LOG_TAG_GETH_RPC_ERROR, - ...data, - ...baseLogMessage, - }) - } - }) -} - -/** - * This method generates key derivation index for loadtest clients and threads - * - * @param pod the pod replica number - * @param thread the thread number inside the pod - */ -export function getIndexForLoadTestThread(pod: number, thread: number) { - if (thread > MAX_LOADTEST_THREAD_COUNT) { - throw new Error(`thread count must be smaller than ${MAX_LOADTEST_THREAD_COUNT}`) - } - // max number of threads to avoid overlap is [0, MAX_LOADTEST_THREAD_COUNT) - return pod * MAX_LOADTEST_THREAD_COUNT + thread -} - -/** - * This method sends ERC20 tokens - * - * @param kit instance of the contract kit - * @param token the token contract to use - * @param from sender to send the token from - * @param to receiver that gets the tokens - * @param amount the amount of tokens to be sent - * @param password the password of the account to use - * @param txParams additional transaction parameters - * @param onTransactionHash callback, fired when the transaction has is generated - * @param onReceipt callback, fired when the receipt is returned - * @param onError callback, fired in case of an error, containing the error - */ -export const transferERC20Token = async ( - kit: ContractKit, - token: GoldTokenWrapper | StableTokenWrapper, - from: string, - to: string, - amount: BigNumber, - password: string, - txParams: any = {}, - onTransactionHash?: (hash: string) => void, - onReceipt?: (receipt: CeloTxReceipt) => void, - onError?: (error: any) => void -) => { - txParams.from = from - await unlockAccount(kit.connection.web3, 0, password, from) - - const convertedAmount = await convertToContractDecimals(amount, token) - - try { - const result = await token.transfer(to, convertedAmount.toString()).send() - if (onTransactionHash) { - onTransactionHash(await result.getHash()) - } - if (onReceipt) { - const receipt = await result.waitReceipt() - onReceipt(receipt) - } - } catch (error) { - if (onError) { - onError(error) - } - } -} - -export const runGethNodes = async ({ - gethConfig, - validators, - verbose, -}: { - gethConfig: GethRunConfig - validators: Validator[] - verbose: boolean -}) => { - const gethBinaryPath = path.join( - (gethConfig.repository && gethConfig.repository.path) || '', - 'build/bin/geth' - ) - - if (!fs.existsSync(gethBinaryPath)) { - console.error(`Geth binary at ${gethBinaryPath} not found!`) - return - } - - if (!gethConfig.keepData && fs.existsSync(gethConfig.runPath)) { - await resetDataDir(gethConfig.runPath, verbose) - } - - if (!fs.existsSync(gethConfig.runPath)) { - // @ts-ignore - fs.mkdirSync(gethConfig.runPath, { recursive: true }) - } - - await writeGenesis(gethConfig, validators, verbose) - - if (verbose) { - const validatorAddresses = validators.map((validator) => validator.address) - console.log('Validators', JSON.stringify(validatorAddresses, null, 2)) - } - - for (const instance of gethConfig.instances) { - await initAndStartGeth(gethConfig, gethBinaryPath, instance, verbose) - } - - await connectValidatorPeers(gethConfig.instances) -} - -function getInstanceDir(runPath: string, instance: GethInstanceConfig) { - return path.join(runPath, instance.name) -} - -function getSnapshotdir(runPath: string, instance: GethInstanceConfig) { - return path.join(getInstanceDir(runPath, instance), 'snapshot') -} - -export function importGenesis(genesisPath: string) { - return JSON.parse(fs.readFileSync(genesisPath).toString()) -} - -export function getLogFilename(runPath: string, instance: GethInstanceConfig) { - return path.join(getDatadir(runPath, instance), 'logs.txt') -} - -function getDatadir(runPath: string, instance: GethInstanceConfig) { - const dir = path.join(getInstanceDir(runPath, instance), 'datadir') - // @ts-ignore - fs.mkdirSync(dir, { recursive: true }) - return dir -} - -/** - * @returns Promise the geth pid number - */ -export async function initAndStartGeth( - gethConfig: GethRunConfig, - gethBinaryPath: string, - instance: GethInstanceConfig, - verbose: boolean -) { - await initGeth(gethConfig, gethBinaryPath, instance, verbose) - return startGeth(gethConfig, gethBinaryPath, instance, verbose) -} - -export async function initGeth( - gethConfig: GethRunConfig, - gethBinaryPath: string, - instance: GethInstanceConfig, - verbose: boolean -) { - const datadir = getDatadir(gethConfig.runPath, instance) - const genesisPath = path.join(gethConfig.runPath, 'genesis.json') - if (verbose) { - console.info(`geth:${instance.name}: init datadir ${datadir}`) - console.log(`init geth with genesis at ${genesisPath}`) - } - - await spawnCmdWithExitOnFailure('rm', ['-rf', datadir], { silent: !verbose }) - await spawnCmdWithExitOnFailure(gethBinaryPath, ['--datadir', datadir, 'init', genesisPath], { - silent: !verbose, - }) - if (instance.privateKey) { - await importPrivateKey(gethConfig, gethBinaryPath, instance, verbose) - } -} - -export async function importPrivateKey( - getConfig: GethRunConfig, - gethBinaryPath: string, - instance: GethInstanceConfig, - verbose: boolean -) { - const keyFile = path.join(getDatadir(getConfig.runPath, instance), 'key.txt') - if (!instance.privateKey) { - throw new Error('Unexpected empty private key') - } - fs.writeFileSync(keyFile, instance.privateKey, { flag: 'a' }) - - if (verbose) { - console.info(`geth:${instance.name}: import account`) - } - - const args = [ - 'account', - 'import', - '--datadir', - getDatadir(getConfig.runPath, instance), - '--password', - '/dev/null', - keyFile, - ] - - if (verbose) { - console.log(gethBinaryPath, ...args) - } - - await spawnCmdWithExitOnFailure(gethBinaryPath, args, { silent: true }) -} - -export async function getEnode(peer: string, ws: boolean = false) { - // do we have already an enode? - if (peer.toLowerCase().startsWith('enode')) { - // yes return peer - return peer - } - - // no, try to build it - const p = ws ? 'ws' : 'http' - const enodeRpcUrl = `${p}://localhost:${peer}` - const admin = new Admin(enodeRpcUrl) - - let nodeInfo: any = { - enode: null, - } - - try { - nodeInfo = await admin.getNodeInfo() - } catch { - console.error(`Unable to get node info from ${enodeRpcUrl}`) - } - - return nodeInfo.enode -} - -export async function addStaticPeers(datadir: string, peers: string[], verbose: boolean) { - const staticPeersPath = path.join(datadir, 'static-nodes.json') - if (verbose) { - console.log(`Writing static peers to ${staticPeersPath}`) - } - - const enodes = await Promise.all(peers.map((peer) => getEnode(peer))) - const enodesString = JSON.stringify(enodes, null, 2) - - if (verbose) { - console.log('eNodes', enodesString) - } - - fs.writeFileSync(staticPeersPath, enodesString) -} - -export async function addProxyPeer( - runPath: string, - gethBinaryPath: string, - instance: GethInstanceConfig -) { - if (instance.proxies) { - await spawnCmdWithExitOnFailure(gethBinaryPath, [ - '--datadir', - getDatadir(runPath, instance), - 'attach', - '--exec', - `istanbul.addProxy('${instance.proxies[0]!}', '${instance.proxies[1]!}')`, - ]) - } -} - -export async function startGeth( - gethConfig: GethRunConfig, - gethBinaryPath: string, - instance: GethInstanceConfig, - verbose: boolean -) { - if (verbose) { - console.log('starting geth with config', JSON.stringify(instance, null, 2)) - } else { - console.log(`${instance.name}: starting.`) - } - - const datadir = getDatadir(gethConfig.runPath, instance) - - const { - syncmode, - port, - rpcport, - wsport, - validating, - replica, - validatingGasPrice, - bootnodeEnode, - isProxy, - proxyAllowPrivateIp, - isProxied, - proxyport, - ethstats, - gatewayFee, - } = instance - - const privateKey = instance.privateKey || '' - const lightserv = instance.lightserv || false - const minerValidator = instance.minerValidator - if (instance.validating && !minerValidator) { - throw new Error('miner.validator address from the instance is required') - } - const verbosity = gethConfig.verbosity ? gethConfig.verbosity : '3' - - instance.args = [ - '--datadir', - datadir, - '--syncmode', - syncmode, - '--log.debug', - '--metrics', - '--port', - port.toString(), - '--networkid', - gethConfig.networkId.toString(), - `--verbosity=${verbosity}`, - '--consoleoutput=stdout', // Send all logs to stdout - '--consoleformat=term', - '--nat', - 'extip:127.0.0.1', - '--allow-insecure-unlock', // geth1.9 to use http w/unlocking - '--gcmode=archive', // Needed to retrieve historical state - '--rpc.gasinflationrate=1', // InflationRate=1 (no inflation) - ] - - if (minerValidator) { - const txFeeRecipient = instance.txFeeRecipient || minerValidator - instance.args.push('--miner.validator', minerValidator, '--tx-fee-recipient', txFeeRecipient) - } - - if (rpcport) { - instance.args.push( - '--http', - '--http.port', - rpcport.toString(), - '--http.corsdomain=*', - '--http.vhosts=*', - '--http.api=eth,net,web3,debug,admin,personal,txpool,istanbul' - ) - } - - if (wsport) { - instance.args.push( - '--ws', - '--ws.origins=*', - '--ws.port', - wsport.toString(), - '--ws.api=eth,net,web3,debug,admin,personal,txpool,istanbul' - ) - } - - if (lightserv) { - instance.args.push('--light.serve=90') - instance.args.push('--light.maxpeers=10') - } else if (syncmode === 'full' || syncmode === 'fast') { - instance.args.push('--light.serve=0') - } - - if (instance.nodekey) { - instance.args.push(`--nodekeyhex=${instance.nodekey}`) - } else if (!validating || !replica) { - instance.args.push(`--nodekeyhex=${privateKey}`) - } - - if (gatewayFee) { - instance.args.push(`--light.gatewayfee=${gatewayFee.toString()}`) - } - - if (validating) { - instance.args.push('--mine') - - if (validatingGasPrice) { - instance.args.push(`--miner.gasprice=${validatingGasPrice}`) - } - - if (isProxied) { - instance.args.push('--proxy.proxied') - } - if (replica) { - instance.args.push('--istanbul.replica') - } - } else if (isProxy) { - instance.args.push('--proxy.proxy') - if (proxyport) { - instance.args.push(`--proxy.internalendpoint=:${proxyport.toString()}`) - } - instance.args.push(`--proxy.proxiedvalidatoraddress=${instance.proxiedValidatorAddress}`) - } - - if (bootnodeEnode) { - instance.args.push(`--bootnodes=${bootnodeEnode}`) - } else { - instance.args.push('--nodiscover') - } - - if (isProxied && instance.proxies) { - if (proxyAllowPrivateIp) { - instance.args.push('--proxy.allowprivateip=true') - } - instance.args.push(`--proxy.proxyenodeurlpairs=${instance.proxies[0]!};${instance.proxies[1]!}`) - } - - if (privateKey || ethstats) { - instance.args.push('--password=/dev/null', `--unlock=0`) - } - - if (ethstats) { - instance.args.push(`--ethstats=${instance.name}@${ethstats}`, '--etherbase=0') - } - - const gethProcess = spawnWithLog(gethBinaryPath, instance.args, `${datadir}/logs.txt`, verbose) - instance.pid = gethProcess.pid - - gethProcess.on('error', (err: Error) => { - throw new Error(`geth:${instance.name} failed to start! ${err}`) - }) - - gethProcess.on('exit', (code: number) => { - if (code === 0) { - console.info(`geth:${instance.name} exited`) - } else { - console.error(`geth:${instance.name} exited with code ${code}`) - } - instance.pid = undefined - }) - - // Give some time for geth to come up - const secondsToWait = 30 - if (rpcport) { - const isOpen = await waitForPortOpen('localhost', rpcport, secondsToWait) - if (!isOpen) { - console.error( - `geth:${instance.name}: jsonRPC port ${rpcport} didn't open after ${secondsToWait} seconds` - ) - process.exit(1) - } else if (verbose) { - console.info(`geth:${instance.name}: jsonRPC port open ${rpcport}`) - } - } - - if (wsport) { - const isOpen = await waitForPortOpen('localhost', wsport, secondsToWait) - if (!isOpen) { - console.error( - `geth:${instance.name}: ws port ${wsport} didn't open after ${secondsToWait} seconds` - ) - process.exit(1) - } else if (verbose) { - console.info(`geth:${instance.name}: ws port open ${wsport}`) - } - } - - // Geth startup isn't fully done even when the port is open, so check until it responds - const maxTries = 5 - let tries = 0 - while (tries < maxTries) { - tries++ - let block = null - try { - block = await new Web3('http://localhost:8545').eth.getBlock('latest') - } catch (e) { - console.log(`Failed to fetch test block: ${e}`) - } - if (block) { - break - } - console.log('Could not fetch test block. Wait one second, then retry.') - await sleep(1000) - } - if (tries === maxTries) { - throw new Error(`Geth did not start within ${tries} seconds`) - } - - console.log( - `${instance.name}: running.`, - rpcport ? `RPC: ${rpcport}` : '', - wsport ? `WS: ${wsport}` : '', - proxyport ? `PROXY: ${proxyport}` : '' - ) - - return instance -} - -export function writeGenesis(gethConfig: GethRunConfig, validators: Validator[], verbose: boolean) { - const genesis: string = generateGenesis({ - validators, - blockTime: 1, - epoch: 10, - lookbackwindow: 3, - requestTimeout: 3000, - chainId: gethConfig.networkId, - ...gethConfig.genesisConfig, - }) - - const genesisPath = path.join(gethConfig.runPath, 'genesis.json') - - if (verbose) { - console.log('writing genesis') - } - - fs.writeFileSync(genesisPath, genesis) - - if (verbose) { - console.log(`wrote genesis to ${genesisPath}`) - } -} - -export async function writeGenesisWithMigrations( - gethConfig: GethRunConfig, - gethRepoPath: string, - mnemonic: string, - numValidators: number, - verbose: boolean = false -) { - const genesis: string = await generateGenesisWithMigrations({ - gethRepoPath, - mnemonic, - numValidators, - verbose, - genesisConfig: { - blockTime: 1, - epoch: 10, - lookbackwindow: 3, - requestTimeout: 3000, - chainId: gethConfig.networkId, - ...gethConfig.genesisConfig, - }, - }) - - const genesisPath = path.join(gethConfig.runPath, 'genesis.json') - - if (verbose) { - console.log('writing genesis') - } - - fs.writeFileSync(genesisPath, genesis) - - if (verbose) { - console.log(`wrote genesis to ${genesisPath}`) - } -} - -export async function snapshotDatadir( - runPath: string, - instance: GethInstanceConfig, - verbose: boolean -) { - if (verbose) { - console.log('snapshotting data dir') - } - - // Sometimes the socket is still present, preventing us from snapshotting. - await spawnCmd('rm', [`${getDatadir(runPath, instance)}/geth.ipc`], { silent: true }) - await spawnCmdWithExitOnFailure('cp', [ - '-r', - getDatadir(runPath, instance), - getSnapshotdir(runPath, instance), - ]) -} - -export async function restoreDatadir(runPath: string, instance: GethInstanceConfig) { - const datadir = getDatadir(runPath, instance) - const snapshotdir = getSnapshotdir(runPath, instance) - - console.info(`geth:${instance.name}: restore datadir: ${datadir}`) - - await spawnCmdWithExitOnFailure('rm', ['-rf', datadir], { silent: true }) - await spawnCmdWithExitOnFailure('cp', ['-r', snapshotdir, datadir], { silent: true }) -} - -export async function buildGeth(gethPath: string) { - await spawnCmdWithExitOnFailure('make', ['geth'], { cwd: gethPath }) -} - -export async function buildGethAll(gethPath: string) { - await spawnCmdWithExitOnFailure('make', ['all'], { cwd: gethPath }) -} - -export async function resetDataDir(dataDir: string, verbose: boolean) { - await spawnCmd('rm', ['-rf', dataDir], { silent: !verbose }) - await spawnCmd('mkdir', [dataDir], { silent: !verbose }) -} - -export async function checkoutGethRepo(branch: string, gethPath: string) { - await spawnCmdWithExitOnFailure('rm', ['-rf', gethPath]) - await spawnCmdWithExitOnFailure('git', [ - 'clone', - '--depth', - '1', - 'https://github.com/celo-org/celo-blockchain.git', - gethPath, - '-b', - branch, - ]) - await spawnCmdWithExitOnFailure('git', ['checkout', branch], { cwd: gethPath }) -} - -export function spawnWithLog(cmd: string, args: string[], logsFilepath: string, verbose: boolean) { - try { - fs.unlinkSync(logsFilepath) - } catch (error) { - // nothing to do - } - - const logStream = fs.createWriteStream(logsFilepath, { flags: 'a' }) - - if (verbose) { - console.log(cmd, ...args) - } - - const p = spawn(cmd, args) - - p.stdout.pipe(logStream) - p.stderr.pipe(logStream) - - if (verbose) { - p.stdout.pipe(process.stdout) - p.stderr.pipe(process.stderr) - } - - return p -} - -// Create a fully connected clique of peer connections with the given instances. -export async function connectPeers(instances: GethInstanceConfig[], verbose: boolean = false) { - await connectBipartiteClique(instances, instances, verbose) -} - -// Fully connect all peers in the "left" set to all peers in the "right" set, forming a bipartite clique. -export async function connectBipartiteClique( - left: GethInstanceConfig[], - right: GethInstanceConfig[], - verbose: boolean = false -) { - const admins = (instances: GethInstanceConfig[]) => - instances.map( - ({ wsport, rpcport }) => - new Admin(`${rpcport ? 'http' : 'ws'}://localhost:${rpcport || wsport}`) - ) - - const connect = async (sources: GethInstanceConfig[], targets: GethInstanceConfig[]) => { - const targetEnodes = await Promise.all( - admins(targets).map(async (a) => (await a.getNodeInfo()).enode) - ) - - await Promise.all( - admins(sources).map(async (admin) => { - const sourceEnode = (await admin.getNodeInfo()).enode - await Promise.all( - targetEnodes.map(async (enode) => { - if (sourceEnode === enode) { - return - } - if (verbose) { - console.log(`connecting ${sourceEnode} with ${enode}`) - } - const success = await admin.addPeer(enode) - if (!success) { - throw new Error('Connecting geth peers failed!') - } - }) - ) - }) - ) - } - - await connect(left, right) - await connect(right, left) -} - -// Add validator 0 as a peer of each other validator. -export async function connectValidatorPeers(instances: GethInstanceConfig[]) { - const validators = instances.filter( - (node) => (node.validating && !node.isProxied) || node.isProxy - ) - // Determine which validators are isolated (i.e. currently just that they are not using a bootnode) - const isolated = validators.filter((node) => !node.bootnodeEnode) - if (isolated.length <= 0) { - return - } - - // Determine the root node to connect other validators to. It should be able to join the whole network of validators. - const root = validators.find((node) => node.bootnodeEnode) ?? validators[0] - await connectBipartiteClique([root], isolated) -} - -export async function migrateContracts( - monorepoRoot: string, - validatorPrivateKeys: string[], - attestationKeys: string[], - validators: string[], - to: number = 1000, - overrides: any = {}, - verbose: boolean = true -) { - const migrationOverrides = merge( - { - stableToken: { - initialBalances: { - addresses: validators.map(ensure0x), - values: validators.map(() => '10000000000000000000000'), - }, - oracles: validators.map(ensure0x), - }, - validators: { - validatorKeys: validatorPrivateKeys.map(ensure0x), - attestationKeys: attestationKeys.map(ensure0x), - }, - blockchainParameters: { - uptimeLookbackWindow: 3, // same as our default in `writeGenesis()` - }, - }, - overrides - ) - - const args = [ - '--cwd', - `${monorepoRoot}/packages/protocol`, - 'init-network', - '-n', - 'testing', - '-m', - JSON.stringify(migrationOverrides), - '-t', - to.toString(), - ] - - await spawnCmdWithExitOnFailure('yarn', args, { silent: !verbose }) -} diff --git a/packages/celotool/src/lib/helm_deploy.ts b/packages/celotool/src/lib/helm_deploy.ts deleted file mode 100644 index ac5975c09..000000000 --- a/packages/celotool/src/lib/helm_deploy.ts +++ /dev/null @@ -1,1408 +0,0 @@ -import { concurrentMap } from '@celo/utils/lib/async' -import compareVersions from 'compare-versions' -import fs from 'fs' -import { entries, range } from 'lodash' -import os from 'os' -import path from 'path' -import sleep from 'sleep-promise' -import { GCPClusterConfig } from 'src/lib/k8s-cluster/gcp' -import stringHash from 'string-hash' -import { getKubernetesClusterRegion, switchToClusterFromEnv } from './cluster' -import { - execCmd, - execCmdWithExitOnFailure, - outputIncludes, - spawnCmd, - spawnCmdWithExitOnFailure, -} from './cmd-utils' -import { envTypes, envVar, fetchEnv, fetchEnvOrFallback, monorepoRoot } from './env-utils' -import { ensureAuthenticatedGcloudAccount } from './gcloud_utils' -import { generateGenesisFromEnv } from './generate_utils' -import { - buildGethAll, - checkoutGethRepo, - getEnodesWithExternalIPAddresses, - retrieveBootnodeIPAddress, -} from './geth' -import { BaseClusterConfig, CloudProvider } from './k8s-cluster/base' -import { getStatefulSetReplicas, scaleResource } from './kubernetes' -import { installPrometheusIfNotExists } from './prometheus' -import { - getGenesisBlockFromGoogleStorage, - getProxiesPerValidator, - getProxyName, - uploadGenesisBlockToGoogleStorage, -} from './testnet-utils' -import { stringToBoolean } from './utils' - -const generator = require('generate-password') - -const CLOUDSQL_SECRET_NAME = 'blockscout-cloudsql-credentials' -const BACKUP_GCS_SECRET_NAME = 'backup-blockchain-credentials' -const TIMEOUT_FOR_LOAD_BALANCER_POLL = 1000 * 60 * 25 // 25 minutes -const LOAD_BALANCER_POLL_INTERVAL = 1000 * 10 // 10 seconds - -const TESTNET_CHART_DIR = '../helm-charts/testnet' -export type HelmAction = 'install' | 'upgrade' - -async function validateExistingCloudSQLInstance(instanceName: string) { - await ensureAuthenticatedGcloudAccount() - try { - await execCmd(`gcloud sql instances describe ${instanceName}`) - } catch (error) { - console.error(`Cloud SQL DB ${instanceName} does not exist, bailing`) - console.error(error) - process.exit(1) - } -} - -async function failIfSecretMissing(secretName: string, namespace: string) { - try { - await execCmd(`kubectl get secret ${secretName} --namespace ${namespace}`) - } catch (error) { - console.error( - `Couldn't retrieve service account secret, cluster is likely not setup correctly for deployment` - ) - console.error(error) - process.exit(1) - } -} - -async function copySecret(secretName: string, srcNamespace: string, destNamespace: string) { - console.info(`Copying secret ${secretName} from namespace ${srcNamespace} to ${destNamespace}`) - await execCmdWithExitOnFailure(`kubectl get secret ${secretName} --namespace ${srcNamespace} -o yaml |\ - grep -v creationTimestamp | grep -v resourceVersion | grep -v selfLink | grep -v uid |\ - sed 's/default/${destNamespace}/' | kubectl apply --namespace=${destNamespace} -f -`) -} - -export async function createCloudSQLInstance(celoEnv: string, instanceName: string) { - await ensureAuthenticatedGcloudAccount() - console.info('Creating Cloud SQL database, this might take a minute or two ...') - - await failIfSecretMissing(CLOUDSQL_SECRET_NAME, 'default') - - try { - await execCmd(`gcloud sql instances describe ${instanceName}`) - // if we get to here, that means the instance already exists - console.warn( - `A Cloud SQL instance named ${instanceName} already exists, so in all likelihood you cannot deploy initial with ${instanceName}` - ) - } catch (error: any) { - if ( - error.message.trim() !== - `Command failed: gcloud sql instances describe ${instanceName}\nERROR: (gcloud.sql.instances.describe) HTTPError 404: The Cloud SQL instance does not exist.` - ) { - console.error(error.message.trim()) - process.exit(1) - } - } - - // Quite often these commands timeout, but actually succeed anyway. By ignoring errors we allow them to be re-run. - - try { - await execCmd( - `gcloud sql instances create ${instanceName} --zone ${fetchEnv( - envVar.KUBERNETES_CLUSTER_ZONE - )} --database-version POSTGRES_9_6 --cpu 1 --memory 4G` - ) - } catch (error: any) { - console.error(error.message.trim()) - } - - const envType = fetchEnv(envVar.ENV_TYPE) - if (envType !== envTypes.DEVELOPMENT) { - try { - await execCmdWithExitOnFailure( - `gcloud sql instances create ${instanceName}-replica --master-instance-name=${instanceName} --zone ${fetchEnv( - envVar.KUBERNETES_CLUSTER_ZONE - )}` - ) - } catch (error: any) { - console.error(error.message.trim()) - } - } - - await execCmdWithExitOnFailure( - `gcloud sql instances patch ${instanceName} --backup-start-time 17:00` - ) - - const passwordOptions = { - length: 22, - numbers: true, - symbols: false, - lowercase: true, - uppercase: true, - strict: true, - } - - const blockscoutDBUsername = generator.generate(passwordOptions) - const blockscoutDBPassword = generator.generate(passwordOptions) - - console.info('Creating SQL user') - await execCmdWithExitOnFailure( - `gcloud sql users create ${blockscoutDBUsername} -i ${instanceName} --password ${blockscoutDBPassword}` - ) - - console.info('Creating blockscout database') - await execCmdWithExitOnFailure(`gcloud sql databases create blockscout -i ${instanceName}`) - - console.info('Copying blockscout service account secret to namespace') - await copySecret(CLOUDSQL_SECRET_NAME, 'default', celoEnv) - - const [blockscoutDBConnectionName] = await execCmdWithExitOnFailure( - `gcloud sql instances describe ${instanceName} --format="value(connectionName)"` - ) - - return [blockscoutDBUsername, blockscoutDBPassword, blockscoutDBConnectionName.trim()] -} - -export async function cloneCloudSQLInstance( - celoEnv: string, - instanceName: string, - cloneInstanceName: string, - dbSuffix: string -) { - await ensureAuthenticatedGcloudAccount() - console.info('Cloning Cloud SQL database, this might take a minute or two ...') - - await failIfSecretMissing(CLOUDSQL_SECRET_NAME, 'default') - - try { - await execCmd(`gcloud sql instances describe ${cloneInstanceName}`) - // if we get to here, that means the instance already exists - console.warn( - `A Cloud SQL instance named ${cloneInstanceName} already exists, so in all likelihood you cannot deploy cloning with ${cloneInstanceName}` - ) - } catch (error: any) { - if ( - error.message.trim() !== - `Command failed: gcloud sql instances describe ${cloneInstanceName}\nERROR: (gcloud.sql.instances.describe) HTTPError 404: The Cloud SQL instance does not exist.` - ) { - console.error(error.message.trim()) - process.exit(1) - } - } - - try { - await execCmdWithExitOnFailure( - `gcloud sql instances clone ${instanceName} ${cloneInstanceName} ` - ) - } catch (error: any) { - console.error(error.message.trim()) - } - - await execCmdWithExitOnFailure( - `gcloud sql instances patch ${cloneInstanceName} --backup-start-time 17:00` - ) - - const [blockscoutDBUsername, blockscoutDBPassword] = await retrieveCloudSQLConnectionInfo( - celoEnv, - instanceName, - dbSuffix - ) - - console.info('Copying blockscout service account secret to namespace') - await copySecret(CLOUDSQL_SECRET_NAME, 'default', celoEnv) - - const [blockscoutDBConnectionName] = await execCmdWithExitOnFailure( - `gcloud sql instances describe ${cloneInstanceName} --format="value(connectionName)"` - ) - - return [blockscoutDBUsername, blockscoutDBPassword, blockscoutDBConnectionName.trim()] -} - -export async function createSecretInSecretManagerIfNotExists( - secretId: string, - secretLabels: string[], - secretValue: string -) { - try { - await execCmd(`gcloud secrets describe ${secretId}`) - - console.info(`Secret ${secretId} already exists, skipping creation...`) - } catch (error) { - await execCmd( - `echo -n "${secretValue}" | gcloud secrets create ${secretId} --data-file=- --replication-policy="automatic" --labels ${secretLabels.join( - ',' - )}` - ) - } -} - -export async function deleteSecretFromSecretManager(secretId: string) { - try { - await execCmd(`gcloud secrets delete ${secretId}`) - } catch { - console.info(`Couldn't delete secret ${secretId} -- skipping`) - } -} - -async function createAndUploadKubernetesSecretIfNotExists( - secretName: string, - serviceAccountName: string, - celoEnv: string -) { - await switchToClusterFromEnv(celoEnv) - const keyfilePath = `/tmp/${serviceAccountName}_key.json` - const secretExists = await outputIncludes( - `kubectl get secrets`, - secretName, - `secret exists, skipping creation: ${secretName}` - ) - if (!secretExists) { - console.info(`Creating secret ${secretName}`) - await execCmdWithExitOnFailure( - `gcloud iam service-accounts keys create ${keyfilePath} --iam-account ${serviceAccountName}@${fetchEnv( - envVar.TESTNET_PROJECT_NAME - )}.iam.gserviceaccount.com` - ) - await execCmdWithExitOnFailure( - `kubectl create secret generic ${secretName} --from-file=credentials.json=${keyfilePath}` - ) - } -} - -export async function createAndUploadCloudSQLSecretIfNotExists( - serviceAccountName: string, - celoEnv: string -) { - return createAndUploadKubernetesSecretIfNotExists( - CLOUDSQL_SECRET_NAME, - serviceAccountName, - celoEnv - ) -} - -export async function createAndUploadBackupSecretIfNotExists( - serviceAccountName: string, - celoEnv: string -) { - return createAndUploadKubernetesSecretIfNotExists( - BACKUP_GCS_SECRET_NAME, - serviceAccountName, - celoEnv - ) -} - -export function getServiceAccountName(prefix: string) { - // NOTE: trim to meet the max size requirements of service account names - return `${prefix}-${fetchEnv(envVar.KUBERNETES_CLUSTER_NAME)}`.slice(0, 30) -} - -export async function installGCPSSDStorageClass() { - // A previous version installed this directly with `kubectl` instead of helm. - // To be backward compatible, we don't install the chart if the storage class - // already exists. - const storageClassExists = await outputIncludes( - `kubectl get storageclass`, - `ssd`, - `SSD StorageClass exists, skipping install` - ) - if (!storageClassExists) { - const gcpSSDHelmChartPath = '../helm-charts/gcp-ssd' - await execCmdWithExitOnFailure(`helm upgrade -i gcp-ssd ${gcpSSDHelmChartPath}`) - } -} - -export async function installCertManagerAndNginx( - celoEnv: string, - clusterConfig?: BaseClusterConfig -) { - const nginxChartVersion = '4.2.1' - const nginxChartNamespace = 'default' - - // Check if cert-manager is installed in any namespace - // because cert-manager crds are global and cannot live - // different crds version in the same cluster - const certManagerExists = - (await outputIncludes(`helm list -n default`, `cert-manager-cluster-issuers`)) || - (await outputIncludes(`helm list -n cert-manager`, `cert-manager-cluster-issuers`)) - - if (certManagerExists) { - console.info('cert-manager-cluster-issuers exists, skipping install') - } else { - await installCertManager() - } - - const nginxIngressReleaseExists = await outputIncludes( - `helm list -n default`, - `nginx-ingress-release`, - `nginx-ingress-release exists, skipping install` - ) - if (!nginxIngressReleaseExists) { - const valueFilePath = `/tmp/${celoEnv}-nginx-testnet-values.yaml` - await nginxHelmParameters(valueFilePath, celoEnv, clusterConfig) - - await helmAddAndUpdateRepos() - await execCmdWithExitOnFailure(`helm install \ - -n ${nginxChartNamespace} \ - --version ${nginxChartVersion} \ - nginx-ingress-release ingress-nginx/ingress-nginx \ - -f ${valueFilePath} - `) - } -} - -async function nginxHelmParameters( - valueFilePath: string, - celoEnv: string, - clusterConfig?: BaseClusterConfig -) { - const logFormat = `{"timestamp": "$time_iso8601", "requestID": "$req_id", "proxyUpstreamName": - "$proxy_upstream_name", "proxyAlternativeUpstreamName": "$proxy_alternative_upstream_name","upstreamStatus": - "$upstream_status", "upstreamAddr": "$upstream_addr","httpRequest":{"requestMethod": - "$request_method", "requestUrl": "$host$request_uri", "status": $status,"requestSize": - "$request_length", "responseSize": "$upstream_response_length", "userAgent": - "$http_user_agent", "remoteIp": "$remote_addr", "referer": "$http_referer", - "latency": "$upstream_response_time s", "protocol":"$server_protocol"}}` - - let loadBalancerIP = '' - if (clusterConfig == null || clusterConfig?.cloudProvider === CloudProvider.GCP) { - loadBalancerIP = await getOrCreateNginxStaticIp(celoEnv, clusterConfig) - } - - const valueFileContent = ` -controller: - autoscaling: - enabled: "true" - minReplicas: 1 - maxReplicas: 10 - targetCPUUtilizationPercentage: 80 - targetMemoryUtilizationPercentage: 80 - config: - log-format-escape-json: "true" - log-format-upstream: '${logFormat}' - metrics: - enabled: "true" - service: - annotations: - prometheus.io/scrape: "true" - prometheus.io/port: "10254" - service: - loadBalancerIP: ${loadBalancerIP} - resources: - requests: - cpu: 300m - memory: 600Mi -` - fs.writeFileSync(valueFilePath, valueFileContent) -} - -async function getOrCreateNginxStaticIp(celoEnv: string, clusterConfig?: BaseClusterConfig) { - const staticIpName = clusterConfig?.clusterName - ? `${clusterConfig?.clusterName}-nginx` - : `${celoEnv}-nginx` - let staticIpAddress - if (clusterConfig !== undefined && clusterConfig.hasOwnProperty('zone')) { - const zone = (clusterConfig as GCPClusterConfig).zone - await registerIPAddress(staticIpName, zone) - staticIpAddress = await retrieveIPAddress(staticIpName, zone) - } else { - await registerIPAddress(staticIpName) - staticIpAddress = await retrieveIPAddress(staticIpName) - } - console.info(`nginx-ingress static ip --> ${staticIpName}: ${staticIpAddress}`) - return staticIpAddress -} - -// Add a Helm repository and updates the local cache. If repository already exists, it is executed -// without error. -export async function helmAddRepoAndUpdate(repository: string, name?: string) { - if (name === undefined) { - const repoArray = repository.split('/') - name = repoArray[repoArray.length - 1] - } - console.info(`Adding Helm repository ${name} with URL ${repository}`) - await execCmdWithExitOnFailure(`helm repo add ${name} ${repository}`) - await execCmdWithExitOnFailure(`helm repo update`) -} - -// Add common helm repositories -export async function helmAddAndUpdateRepos() { - await helmAddRepoAndUpdate('https://kubernetes.github.io/ingress-nginx') - await helmAddRepoAndUpdate('https://charts.helm.sh/stable') - await execCmdWithExitOnFailure(`helm repo update`) -} - -export async function installCertManager() { - const clusterIssuersHelmChartPath = `../helm-charts/cert-manager-cluster-issuers` - - console.info('Create the namespace for cert-manager') - await execCmdWithExitOnFailure(`kubectl create namespace cert-manager`) - - console.info('Installing cert-manager CustomResourceDefinitions') - await execCmdWithExitOnFailure( - `kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.9.1/cert-manager.crds.yaml` - ) - console.info('Updating cert-manager-cluster-issuers chart dependencies') - await execCmdWithExitOnFailure(`helm dependency update ${clusterIssuersHelmChartPath}`) - console.info('Installing cert-manager-cluster-issuers') - await execCmdWithExitOnFailure( - `helm install cert-manager-cluster-issuers ${clusterIssuersHelmChartPath} -n cert-manager` - ) -} - -export async function installAndEnableMetricsDeps( - installPrometheus: boolean, - context?: string, - clusterConfig?: BaseClusterConfig -) { - const kubeStateMetricsReleaseExists = await outputIncludes( - `helm list -n default`, - `kube-state-metrics`, - `kube-state-metrics exists, skipping install` - ) - if (!kubeStateMetricsReleaseExists) { - await execCmdWithExitOnFailure( - `helm install kube-state-metrics stable/kube-state-metrics --set rbac.create=true -n default` - ) - } - if (installPrometheus) { - await installPrometheusIfNotExists(context, clusterConfig) - } -} - -export async function grantRoles(serviceAccountName: string, role: string) { - const projectName = fetchEnv(envVar.TESTNET_PROJECT_NAME) - - const serviceAccountFullName = `${serviceAccountName}@${projectName}.iam.gserviceaccount.com` - const commandRolesAlreadyGranted = `gcloud projects get-iam-policy ${projectName} \ - --flatten="bindings[].members" \ - --format='table(bindings.role)' \ - --filter="bindings.members:serviceAccount:${serviceAccountFullName}"` - const rolesAlreadyGranted = await outputIncludes( - commandRolesAlreadyGranted, - role, - `Role ${role} already granted for account ${serviceAccountFullName}, skipping binding` - ) - if (!rolesAlreadyGranted) { - const cmd = - `gcloud projects add-iam-policy-binding ${projectName} ` + - `--role=${role} ` + - `--member=serviceAccount:${serviceAccountFullName}` - await execCmd(cmd) - } - return -} - -export async function retrieveCloudSQLConnectionInfo( - celoEnv: string, - instanceName: string, - dbSuffix: string -) { - await validateExistingCloudSQLInstance(instanceName) - const secretName = `${celoEnv}-blockscout${dbSuffix}` - const [blockscoutDBUsername] = await execCmdWithExitOnFailure( - `kubectl get secret ${secretName} -o jsonpath='{.data.DATABASE_USER}' -n ${celoEnv} | base64 --decode` - ) - const [blockscoutDBPassword] = await execCmdWithExitOnFailure( - `kubectl get secret ${secretName} -o jsonpath='{.data.DATABASE_PASSWORD}' -n ${celoEnv} | base64 --decode` - ) - const [blockscoutDBConnectionName] = await execCmdWithExitOnFailure( - `gcloud sql instances describe ${instanceName} --format="value(connectionName)"` - ) - - return [blockscoutDBUsername, blockscoutDBPassword, blockscoutDBConnectionName.trim()] -} - -export async function deleteCloudSQLInstance( - instanceName: string -): Promise<[string, string, string]> { - console.info(`Deleting Cloud SQL instance ${instanceName}, this might take a minute or two ...`) - try { - await execCmd(`gcloud sql instances delete ${instanceName} --quiet`) - } catch { - console.info(`Couldn't delete Cloud SQL instance ${instanceName} -- skipping`) - } - return ['', '', ''] -} - -export async function resetCloudSQLInstance(instanceName: string) { - await validateExistingCloudSQLInstance(instanceName) - - console.info('Deleting blockscout database from instance') - await execCmdWithExitOnFailure( - `gcloud sql databases delete blockscout -i ${instanceName} --quiet` - ) - - console.info('Creating blockscout database') - await execCmdWithExitOnFailure(`gcloud sql databases create blockscout -i ${instanceName}`) -} - -export async function registerIPAddress(name: string, zone?: string) { - console.info(`Registering IP address ${name}`) - try { - await execCmd( - `gcloud compute addresses create ${name} --region ${getKubernetesClusterRegion(zone)}` - ) - } catch (error: any) { - if (!error.toString().includes('already exists')) { - console.error(error) - process.exit(1) - } - } -} - -export async function deleteIPAddress(name: string, zone?: string) { - console.info(`Deleting IP address ${name}`) - try { - if (isCelotoolVerbose()) { - console.info(`IP Address ${name} would be deleted`) - } else { - await execCmd( - `gcloud compute addresses delete ${name} --region ${getKubernetesClusterRegion(zone)} -q` - ) - } - } catch (error: any) { - if (!error.toString().includes('was not found')) { - console.error(error) - process.exit(1) - } - } -} - -export async function retrieveIPAddress(name: string, zone?: string) { - const regionFlag = zone === 'global' ? '--global' : `--region ${getKubernetesClusterRegion(zone)}` - const [address] = await execCmdWithExitOnFailure( - `gcloud compute addresses describe ${name} ${regionFlag} --format="value(address)"` - ) - return address.replace(/\n*$/, '') -} - -export async function retrieveIPAddresses(prefix: string, zone?: string) { - const [address] = await execCmdWithExitOnFailure( - `gcloud compute addresses list --filter="name~'${prefix}-' AND name!~'${prefix}-private-' AND region:( ${getKubernetesClusterRegion( - zone - )} )" --format="value(name)"` - ) - return address.split('\n') -} - -// returns the IP address of a resource internal to the cluster (ie 10.X.X.X) -export async function retrieveClusterIPAddress( - resourceType: string, - resourceName: string, - namespace: string -) { - const [address] = await execCmdWithExitOnFailure( - `kubectl get ${resourceType} ${resourceName} -n ${namespace} -o jsonpath={.spec.clusterIP}` - ) - return address -} - -export async function createStaticIPs(celoEnv: string) { - console.info(`Creating static IPs for ${celoEnv}`) - - const numTxNodes = parseInt(fetchEnv(envVar.TX_NODES), 10) - await concurrentMap(5, range(numTxNodes), (i) => registerIPAddress(`${celoEnv}-tx-nodes-${i}`)) - - if (useStaticIPsForGethNodes()) { - await registerIPAddress(`${celoEnv}-bootnode`) - - const validatorCount = parseInt(fetchEnv(envVar.VALIDATORS), 10) - const proxiesPerValidator = getProxiesPerValidator() - // only create IPs for validators that are not proxied - for (let i = 0; i < validatorCount; i++) { - if (proxiesPerValidator[i] === 0) { - await registerIPAddress(`${celoEnv}-validators-${i}`) - } - } - - // and create IPs for all the proxies - let validatorIndex = 0 - for (const proxyCount of proxiesPerValidator) { - for (let i = 0; i < proxyCount; i++) { - await registerIPAddress(getProxyName(celoEnv, validatorIndex, i)) - } - validatorIndex++ - } - - // Create IPs for the private tx nodes - const numPrivateTxNodes = parseInt(fetchEnv(envVar.PRIVATE_TX_NODES), 10) - await concurrentMap(5, range(numPrivateTxNodes), (i) => - registerIPAddress(`${celoEnv}-tx-nodes-private-${i}`) - ) - } -} - -export async function upgradeStaticIPs(celoEnv: string) { - const newTxNodeCount = parseInt(fetchEnv(envVar.TX_NODES), 10) - await upgradeNodeTypeStaticIPs(celoEnv, 'tx-nodes', newTxNodeCount) - - if (useStaticIPsForGethNodes()) { - const prevValidatorNodeCount = await getStatefulSetReplicas(celoEnv, `${celoEnv}-validators`) - const newValidatorNodeCount = parseInt(fetchEnv(envVar.VALIDATORS), 10) - await upgradeValidatorStaticIPs(celoEnv, prevValidatorNodeCount, newValidatorNodeCount) - - const proxiesPerValidator = getProxiesPerValidator() - // Iterate through all validators and check to see if there are changes in proxies - const higherValidatorCount = Math.max(prevValidatorNodeCount, newValidatorNodeCount) - for (let i = 0; i < higherValidatorCount; i++) { - const proxyCount = proxiesPerValidator[i] - await upgradeNodeTypeStaticIPs(celoEnv, `validators-${i}-proxy`, proxyCount) - } - - const newPrivateTxNodeCount = parseInt(fetchEnv(envVar.PRIVATE_TX_NODES), 10) - await upgradeNodeTypeStaticIPs(celoEnv, 'tx-nodes-private', newPrivateTxNodeCount) - } -} - -async function upgradeValidatorStaticIPs( - celoEnv: string, - prevValidatorNodeCount: number, - newValidatorNodeCount: number -) { - const proxiesPerValidator = getProxiesPerValidator() - - // Iterate through each validator & create or destroy - // IP addresses as necessary. If a validator has a 1+ proxies, - // the validator do not have a static IP. If the validator has - // no proxy, then the validator needs a static ip. - const higherValidatorCount = Math.max(prevValidatorNodeCount, newValidatorNodeCount) - for (let i = 0; i < higherValidatorCount; i++) { - const ipName = `${celoEnv}-validators-${i}` - let ipExists - try { - await retrieveIPAddress(ipName) - ipExists = true - } catch (e) { - ipExists = false - } - const proxiedValidator = proxiesPerValidator[i] === 0 ? false : true - if (ipExists && proxiedValidator) { - await deleteIPAddress(ipName) - } else if (!ipExists && !proxiedValidator) { - await registerIPAddress(ipName) - } - } -} - -async function upgradeNodeTypeStaticIPs(celoEnv: string, nodeType: string, newNodeCount: number) { - const existingAddresses = await retrieveIPAddresses(`${celoEnv}-${nodeType}`) - const desiredAddresses = range(0, newNodeCount).map((i) => `${celoEnv}-${nodeType}-${i}`) - const addressesToCreate = desiredAddresses.filter((a) => !existingAddresses.includes(a)) - const addressesToDelete = existingAddresses.filter((a) => !desiredAddresses.includes(a)) - - for (const address of addressesToCreate) { - if (address) { - await registerIPAddress(address) - } - } - - for (const address of addressesToDelete) { - if (address) { - await deleteIPAddress(address) - } - } -} - -export async function pollForBootnodeLoadBalancer(celoEnv: string) { - if (!useStaticIPsForGethNodes()) { - return - } - console.info(`Poll for bootnode load balancer`) - let totalTime = 0 - - while (true) { - const [rules] = await execCmdWithExitOnFailure( - `gcloud compute addresses describe ${celoEnv}-bootnode --region ${getKubernetesClusterRegion()} --format="value(users.len())"` - ) - - if (parseInt(rules, 10) > 0) { - break - } - - totalTime += LOAD_BALANCER_POLL_INTERVAL - if (totalTime > TIMEOUT_FOR_LOAD_BALANCER_POLL) { - console.error( - `\nCould not detect the bootnode's load balancer provisioning, which will likely cause the peers on the network unable to connect` - ) - process.exit(1) - } - - process.stdout.write('.') - await sleep(LOAD_BALANCER_POLL_INTERVAL) - } - - console.info('Sleeping 1 minute...') - await sleep(1000 * 60) // 1 minute - - console.info(`\nReset all pods now that the bootnode load balancer has provisioned`) - await execCmdWithExitOnFailure(`kubectl delete pod -n ${celoEnv} --selector=component=validators`) - await execCmdWithExitOnFailure(`kubectl delete pod -n ${celoEnv} --selector=component=tx_nodes`) - await execCmdWithExitOnFailure(`kubectl delete pod -n ${celoEnv} --selector=component=proxy`) - return -} - -export async function deleteStaticIPs(celoEnv: string) { - console.info(`Deleting static IPs for ${celoEnv}`) - - const numTxNodes = parseInt(fetchEnv(envVar.TX_NODES), 10) - await concurrentMap(5, range(numTxNodes), (i) => deleteIPAddress(`${celoEnv}-tx-nodes-${i}`)) - - await deleteIPAddress(`${celoEnv}-bootnode`) - - const numValidators = parseInt(fetchEnv(envVar.VALIDATORS), 10) - await concurrentMap(5, range(numValidators), (i) => deleteIPAddress(`${celoEnv}-validators-${i}`)) - - const proxiesPerValidator = getProxiesPerValidator() - for (let valIndex = 0; valIndex < numValidators; valIndex++) { - for (let proxyIndex = 0; proxyIndex < proxiesPerValidator[valIndex]; proxyIndex++) { - await deleteIPAddress(getProxyName(celoEnv, valIndex, proxyIndex)) - } - } - - const numPrivateTxNodes = parseInt(fetchEnv(envVar.PRIVATE_TX_NODES), 10) - await concurrentMap(5, range(numPrivateTxNodes), (i) => - deleteIPAddress(`${celoEnv}-tx-nodes-private-${i}`) - ) -} - -export async function deletePersistentVolumeClaims(celoEnv: string, componentLabels: string[]) { - for (const component of componentLabels) { - await deletePersistentVolumeClaimsCustomLabels(celoEnv, 'component', component) - } -} - -export async function deletePersistentVolumeClaimsCustomLabels( - namespace: string, - label: string, - value: string -) { - console.info( - `Deleting persistent volume claims for labels ${label}=${value} in namespace ${namespace}` - ) - try { - const [output] = await execCmd( - `kubectl delete pvc --selector='${label}=${value}' --namespace ${namespace}` - ) - console.info(output) - } catch (error: any) { - console.error(error) - if (!error.toString().includes('not found')) { - process.exit(1) - } - } -} - -async function helmIPParameters(celoEnv: string) { - const ipAddressParameters: string[] = [ - `--set geth.static_ips=${fetchEnv(envVar.STATIC_IPS_FOR_GETH_NODES)}`, - ] - - const numTxNodes = parseInt(fetchEnv(envVar.TX_NODES), 10) - - const txAddresses = await concurrentMap(5, range(numTxNodes), (i) => - retrieveIPAddress(`${celoEnv}-tx-nodes-${i}`) - ) - - // Tx-node IPs - const txNodeIpParams = setHelmArray('geth.txNodesIPAddressArray', txAddresses) - ipAddressParameters.push(...txNodeIpParams) - - if (useStaticIPsForGethNodes()) { - ipAddressParameters.push( - `--set geth.bootnodeIpAddress=${await retrieveBootnodeIPAddress(celoEnv)}` - ) - - // Validator IPs - const numValidators = parseInt(fetchEnv(envVar.VALIDATORS), 10) - const proxiesPerValidator = getProxiesPerValidator() - // This tracks validator IP addresses for each corresponding validator. If the validator - // is proxied, there is no public IP address, so it's set as an empty string - const validatorIpAddresses = [] - for (let i = 0; i < numValidators; i++) { - if (proxiesPerValidator[i] > 0) { - // Then this validator is proxied - validatorIpAddresses.push('') - } else { - validatorIpAddresses.push(await retrieveIPAddress(`${celoEnv}-validators-${i}`)) - } - } - const validatorIpParams = setHelmArray('geth.validatorsIPAddressArray', validatorIpAddresses) - ipAddressParameters.push(...validatorIpParams) - - // Proxy IPs - // Helm ran into issues when dealing with 2-d lists, - // so each index corresponds to a particular validator. - // Multiple proxy IPs for a single validator are separated by '/' - const proxyIpAddressesPerValidator = [] - let validatorIndex = 0 - for (const proxyCount of proxiesPerValidator) { - const proxyIpAddresses = [] - for (let i = 0; i < proxyCount; i++) { - proxyIpAddresses.push(await retrieveIPAddress(getProxyName(celoEnv, validatorIndex, i))) - } - const listOfProxyIpAddresses = proxyIpAddresses.join('/') - proxyIpAddressesPerValidator.push(listOfProxyIpAddresses) - - validatorIndex++ - } - - const proxyIpAddressesParams = setHelmArray( - 'geth.proxyIPAddressesPerValidatorArray', - proxyIpAddressesPerValidator - ) - ipAddressParameters.push(...proxyIpAddressesParams) - - const numPrivateTxNodes = parseInt(fetchEnv(envVar.PRIVATE_TX_NODES), 10) - const privateTxAddresses = await concurrentMap(5, range(numPrivateTxNodes), (i) => - retrieveIPAddress(`${celoEnv}-tx-nodes-private-${i}`) - ) - const privateTxAddressParameters = privateTxAddresses.map( - (address, i) => `--set geth.private_tx_nodes_${i}IpAddress=${address}` - ) - ipAddressParameters.push(...privateTxAddressParameters) - const listOfPrivateTxNodeAddresses = privateTxAddresses.join(',') - ipAddressParameters.push( - `--set geth.private_tx_node_ip_addresses='{${listOfPrivateTxNodeAddresses}}'` - ) - } - - return ipAddressParameters -} - -async function helmParameters(celoEnv: string, useExistingGenesis: boolean) { - const valueFilePath = `/tmp/${celoEnv}-testnet-values.yaml` - await saveHelmValuesFile(celoEnv, valueFilePath, useExistingGenesis, false) - - const gethMetricsOverrides = - fetchEnvOrFallback('GETH_ENABLE_METRICS', 'false') === 'true' - ? [ - `--set metrics="true"`, - `--set pprof.enabled="true"`, - `--set pprof.path="/debug/metrics/prometheus"`, - `--set pprof.port="6060"`, - ] - : [`--set metrics="false"`, `--set pprof.enabled="false"`] - - const useMyCelo = stringToBoolean(fetchEnvOrFallback(envVar.GETH_USE_MYCELO, 'false')) - await createAndPushGenesis(celoEnv, !useExistingGenesis, useMyCelo) - - const bootnodeOverwritePkey = - fetchEnvOrFallback(envVar.GETH_BOOTNODE_OVERWRITE_PKEY, '') !== '' - ? [ - `--set geth.overwriteBootnodePrivateKey="true"`, - `--set geth.bootnodePrivateKey="${fetchEnv(envVar.GETH_BOOTNODE_OVERWRITE_PKEY)}"`, - ] - : [`--set geth.overwriteBootnodePrivateKey="false"`] - - const defaultDiskSize = fetchEnvOrFallback(envVar.NODE_DISK_SIZE_GB, '10') - const privateTxNodeDiskSize = fetchEnvOrFallback( - envVar.PRIVATE_NODE_DISK_SIZE_GB, - defaultDiskSize - ) - - return [ - `-f ${valueFilePath}`, - `--set bootnode.image.repository=${fetchEnv('GETH_BOOTNODE_DOCKER_IMAGE_REPOSITORY')}`, - `--set bootnode.image.tag=${fetchEnv('GETH_BOOTNODE_DOCKER_IMAGE_TAG')}`, - `--set celotool.image.repository=${fetchEnv('CELOTOOL_DOCKER_IMAGE_REPOSITORY')}`, - `--set celotool.image.tag=${fetchEnv('CELOTOOL_DOCKER_IMAGE_TAG')}`, - `--set domain.name=${fetchEnv('CLUSTER_DOMAIN_NAME')}`, - `--set genesis.useGenesisFileBase64="false"`, - `--set genesis.network=${celoEnv}`, - `--set genesis.networkId=${fetchEnv(envVar.NETWORK_ID)}`, - `--set geth.verbosity=${fetchEnvOrFallback('GETH_VERBOSITY', '4')}`, - `--set geth.vmodule=${fetchEnvOrFallback('GETH_VMODULE', '')}`, - `--set geth.resources.requests.cpu=${fetchEnv('GETH_NODE_CPU_REQUEST')}`, - `--set geth.resources.requests.memory=${fetchEnv('GETH_NODE_MEMORY_REQUEST')}`, - `--set geth.image.repository=${fetchEnv('GETH_NODE_DOCKER_IMAGE_REPOSITORY')}`, - `--set geth.image.tag=${fetchEnv('GETH_NODE_DOCKER_IMAGE_TAG')}`, - `--set geth.validators="${fetchEnv('VALIDATORS')}"`, - `--set geth.secondaries="${fetchEnvOrFallback('SECONDARIES', '0')}"`, - `--set geth.use_gstorage_data=${fetchEnvOrFallback('USE_GSTORAGE_DATA', 'false')}`, - `--set geth.gstorage_data_bucket=${fetchEnvOrFallback('GSTORAGE_DATA_BUCKET', '')}`, - `--set geth.faultyValidators="${fetchEnvOrFallback('FAULTY_VALIDATORS', '0')}"`, - `--set geth.faultyValidatorType="${fetchEnvOrFallback('FAULTY_VALIDATOR_TYPE', '0')}"`, - `--set geth.tx_nodes="${fetchEnv('TX_NODES')}"`, - `--set geth.private_tx_nodes="${fetchEnv(envVar.PRIVATE_TX_NODES)}"`, - `--set geth.ssd_disks="${fetchEnvOrFallback(envVar.GETH_NODES_SSD_DISKS, 'true')}"`, - `--set geth.account.secret="${fetchEnv('GETH_ACCOUNT_SECRET')}"`, - `--set geth.ping_ip_from_packet=${fetchEnvOrFallback('PING_IP_FROM_PACKET', 'false')}`, - `--set geth.in_memory_discovery_table=${fetchEnvOrFallback( - 'IN_MEMORY_DISCOVERY_TABLE', - 'false' - )}`, - `--set geth.diskSizeGB=${defaultDiskSize}`, - `--set geth.privateTxNodediskSizeGB=${privateTxNodeDiskSize}`, - `--set mnemonic="${fetchEnv('MNEMONIC')}"`, - ...setHelmArray('geth.proxiesPerValidator', getProxiesPerValidator()), - ...gethMetricsOverrides, - ...bootnodeOverwritePkey, - ...rollingUpdateHelmVariables(), - ...(await helmIPParameters(celoEnv)), - ] -} - -async function helmCommand(command: string, pipeOutput = false) { - // "helm diff" is a plugin and doesn't support "--debug" - if (isCelotoolVerbose() && !command.startsWith('helm diff')) { - command += ' --debug' - } - - await execCmdWithExitOnFailure(command, {}, pipeOutput) -} - -function buildHelmChartDependencies(chartDir: string) { - console.info(`Building any chart dependencies...`) - return helmCommand(`helm dep build ${chartDir}`) -} - -export async function installHelmDiffPlugin() { - try { - await execCmd(`helm diff version`, {}, false) - } catch (error) { - console.info(`Installing helm-diff plugin...`) - await execCmdWithExitOnFailure(`helm plugin install https://github.com/databus23/helm-diff`) - } -} - -// Return the values file arg if file exists If values file reference is defined and file not found, -// throw an error. When chartDir is a remote chart, the values file is assumed to be an abslute path. -function valuesOverrideArg(chartDir: string, filename: string | undefined) { - if (filename === undefined) { - return '' - } else if (fs.existsSync(filename)) { - return `-f ${filename}` - } else if (fs.existsSync(path.join(chartDir, filename))) { - return `-f ${path.join(chartDir, filename)}` - } else { - console.error(`Values override file ${filename} not found`) - } -} - -// namespace: The namespace to install the chart into -// releaseName: The name of the release -// chartDir: The directory containing the chart or the values.yamls files. By default, it will try to use a custom values file -// at ${chartDir}/${valuesOverrideFile}.yaml -// parameters: The parameters to pass to the helm install command (e.g. --set geth.replicas=3) -// buildDependencies: Whether to build the chart dependencies before installing. When using a remote chart, this must be false. -// chartVersion: The version of the chart to install. Used only when chartRemoteReference is set -// valuesOverrideFile: The name of the values file to use. In the case of a remote chart, this is assumed to be an absolute path. -interface GenericHelmChartParameters { - namespace: string - releaseName: string - chartDir: string - parameters: string[] - buildDependencies?: boolean - chartVersion?: string - valuesOverrideFile?: string -} -// Install a Helm Chart. Look above for the parameters - -// When using a remote helm chart, buildDependencies must be false and valuesOverrideFile the absolute path to the values file -export async function installGenericHelmChart({ - namespace, - releaseName, - chartDir, - parameters, - buildDependencies = true, - chartVersion, - valuesOverrideFile, -}: GenericHelmChartParameters) { - if (buildDependencies) { - await buildHelmChartDependencies(chartDir) - } - - if (isCelotoolHelmDryRun()) { - const versionLog = chartVersion ? ` version ${chartVersion}` : '' - const valuesOverrideLog = valuesOverrideFile - ? `, with values override: ${valuesOverrideFile}` - : '' - console.info( - `This would deploy chart ${chartDir}${versionLog} with release name ${releaseName} in namespace ${namespace}${valuesOverrideLog} with parameters:` - ) - console.info(parameters) - } else { - console.info(`Installing helm release ${releaseName}`) - const versionArg = chartVersion ? `--version=${chartVersion}` : '' - const valuesOverride = valuesOverrideArg(chartDir, valuesOverrideFile) - await helmCommand( - `helm upgrade --install ${valuesOverride} ${releaseName} ${chartDir} ${versionArg} --namespace ${namespace} ${parameters.join( - ' ' - )}` - ) - } -} - -// Upgrade a Helm Chart. chartDir can be the path to the Helm Chart or the name of a remote Helm Chart. -// If using a remote helm chart, the chart repository has to be added and updated in the local helm config -// When using a remote helm chart, buildDependencies must be false and valuesOverrideFile the absolute path to the values file -export async function upgradeGenericHelmChart({ - namespace, - releaseName, - chartDir, - parameters, - buildDependencies = true, - chartVersion, - valuesOverrideFile, -}: GenericHelmChartParameters) { - if (buildDependencies) { - await buildHelmChartDependencies(chartDir) - } - const valuesOverride = valuesOverrideArg(chartDir, valuesOverrideFile) - const versionArg = chartVersion ? `--version=${chartVersion}` : '' - - if (isCelotoolHelmDryRun()) { - console.info( - `Simulating the upgrade of helm release ${releaseName}. No output means no change in the helm release` - ) - await installHelmDiffPlugin() - await helmCommand( - `helm diff upgrade --install -C 5 ${valuesOverride} ${versionArg} ${releaseName} ${chartDir} --namespace ${namespace} ${parameters.join( - ' ' - )}`, - true - ) - } else { - console.info(`Upgrading helm release ${releaseName}`) - await helmCommand( - `helm upgrade --install ${valuesOverride} ${versionArg} ${releaseName} ${chartDir} --timeout 120h --namespace ${namespace} ${parameters.join( - ' ' - )}` - ) - console.info(`Upgraded helm release ${releaseName} successful`) - } -} - -export async function getConfigMapHashes( - celoEnv: string, - releaseName: string, - chartDir: string, - parameters: string[], - action: HelmAction, - valuesOverrideFile?: string -): Promise> { - const valuesOverride = valuesOverrideArg(chartDir, valuesOverrideFile) - const [output] = await execCmd( - `helm ${action} -f ${chartDir}/values.yaml ${valuesOverride} ${releaseName} ${chartDir} --namespace ${celoEnv} ${parameters.join( - ' ' - )} --dry-run`, - {}, - false, - false - ) - - return output - .split('---') - .filter((section) => { - return /kind: ConfigMap/.exec(section) - }) - .reduce>((configHashes, section) => { - const matchSource = /Source: (.*)/.exec(section) - if (matchSource === null) { - throw new Error('Can not extract Source from config section') - } - - configHashes[matchSource[1]] = stringHash(section).toString() - return configHashes - }, {}) -} - -export function isCelotoolVerbose() { - return process.env.CELOTOOL_VERBOSE === 'true' -} - -export function isCelotoolHelmDryRun() { - return process.env.CELOTOOL_HELM_DRY_RUN === 'true' -} - -export function exitIfCelotoolHelmDryRun() { - if (isCelotoolHelmDryRun()) { - console.error('Option --helmdryrun is not allowed for this command. Exiting.') - process.exit(1) - } -} - -export async function removeGenericHelmChart(releaseName: string, namespace: string) { - console.info(`Deleting helm chart ${releaseName} from namespace ${namespace}`) - try { - await execCmd(`helm uninstall --namespace ${namespace} ${releaseName}`) - } catch (error) { - console.error(error) - } -} - -function getExtraValuesFile(celoEnv: string) { - const extraValuesFile = fs.existsSync(`${TESTNET_CHART_DIR}/values-${celoEnv}.yaml`) - ? `values-${celoEnv}.yaml` - : undefined - return extraValuesFile -} - -export async function installHelmChart(celoEnv: string, useExistingGenesis: boolean) { - await failIfSecretMissing(BACKUP_GCS_SECRET_NAME, 'default') - await copySecret(BACKUP_GCS_SECRET_NAME, 'default', celoEnv) - const extraValuesFile = getExtraValuesFile(celoEnv) - return installGenericHelmChart({ - namespace: celoEnv, - releaseName: celoEnv, - chartDir: TESTNET_CHART_DIR, - parameters: await helmParameters(celoEnv, useExistingGenesis), - buildDependencies: true, - valuesOverrideFile: extraValuesFile, - }) -} - -export async function upgradeHelmChart(celoEnv: string, useExistingGenesis: boolean) { - console.info(`Upgrading helm release ${celoEnv}`) - const parameters = await helmParameters(celoEnv, useExistingGenesis) - const extraValuesFile = getExtraValuesFile(celoEnv) - await upgradeGenericHelmChart({ - namespace: celoEnv, - releaseName: celoEnv, - chartDir: TESTNET_CHART_DIR, - parameters, - buildDependencies: true, - valuesOverrideFile: extraValuesFile, - }) -} - -export async function resetAndUpgradeHelmChart(celoEnv: string, useExistingGenesis: boolean) { - const txNodesSetName = `${celoEnv}-tx-nodes` - const validatorsSetName = `${celoEnv}-validators` - const bootnodeName = `${celoEnv}-bootnode` - const privateTxNodesSetname = `${celoEnv}-tx-nodes-private` - const persistentVolumeClaimsLabels = ['validators', 'tx_nodes', 'proxy', 'tx_nodes_private'] - - if (isCelotoolHelmDryRun()) { - // If running dryrun we just want to simulate the helm changes - await upgradeHelmChart(celoEnv, useExistingGenesis) - } else { - // scale down nodes - await scaleResource(celoEnv, 'StatefulSet', txNodesSetName, 0) - await scaleResource(celoEnv, 'StatefulSet', validatorsSetName, 0) - // allow to fail for the cases where a testnet does not include the privatetxnode statefulset yet - await scaleResource(celoEnv, 'StatefulSet', privateTxNodesSetname, 0, true) - await scaleProxies(celoEnv, 0) - await scaleResource(celoEnv, 'Deployment', bootnodeName, 0) - - await deletePersistentVolumeClaims(celoEnv, persistentVolumeClaimsLabels) - await sleep(10000) - - await upgradeHelmChart(celoEnv, useExistingGenesis) - await sleep(10000) - - const numValdiators = parseInt(fetchEnv(envVar.VALIDATORS), 10) - const numTxNodes = parseInt(fetchEnv(envVar.TX_NODES), 10) - const numPrivateTxNodes = parseInt(fetchEnv(envVar.PRIVATE_TX_NODES), 10) - - // Note(trevor): helm upgrade only compares the current chart to the - // previously deployed chart when deciding what needs changing, so we need - // to manually scale up to account for when a node count is the same - await scaleResource(celoEnv, 'StatefulSet', txNodesSetName, numTxNodes) - await scaleResource(celoEnv, 'StatefulSet', validatorsSetName, numValdiators) - await scaleResource(celoEnv, 'StatefulSet', privateTxNodesSetname, numPrivateTxNodes) - await scaleProxies(celoEnv) - await scaleResource(celoEnv, 'Deployment', bootnodeName, 1) - } -} - -// scaleProxies scales all proxy statefulsets to have `replicas` replicas. -// If `replicas` is undefined, proxies will be scaled to their intended -// replica counts -async function scaleProxies(celoEnv: string, replicas?: number) { - if (replicas !== undefined) { - const statefulsetNames = await getProxyStatefulsets(celoEnv) - for (const name of statefulsetNames) { - await scaleResource(celoEnv, 'StatefulSet', name, replicas) - } - } else { - const proxiesPerValidator = getProxiesPerValidator() - let validatorIndex = 0 - for (const proxyCount of proxiesPerValidator) { - // allow to fail for the cases where a testnet does not include the proxy statefulset yet - await scaleResource( - celoEnv, - 'StatefulSet', - `${celoEnv}-validators-${validatorIndex}-proxy`, - proxyCount, - true - ) - validatorIndex++ - } - } -} - -async function getProxyStatefulsets(celoEnv: string) { - const [output] = await execCmd( - `kubectl get statefulsets --selector=component=proxy --no-headers -o custom-columns=":metadata.name" -n ${celoEnv}` - ) - if (!output) { - return [] - } - return output.split('\n').filter((name) => name) -} - -export async function removeHelmRelease(celoEnv: string) { - return removeGenericHelmChart(celoEnv, celoEnv) -} - -export function makeHelmParameters(map: { [key: string]: string }) { - return entries(map).map(([key, value]) => `--set ${key}=${value}`) -} - -export function setHelmArray(paramName: string, arr: any[]) { - return arr.map((value, i) => `--set ${paramName}[${i}]="${value}"`) -} - -export async function deleteFromCluster(celoEnv: string) { - await removeHelmRelease(celoEnv) - console.info(`Deleting namespace ${celoEnv}`) - await execCmdWithExitOnFailure(`kubectl delete namespace ${celoEnv}`) -} - -function useStaticIPsForGethNodes() { - return fetchEnv(envVar.STATIC_IPS_FOR_GETH_NODES) === 'true' -} - -export async function checkHelmVersion() { - const requiredMinHelmVersion = '3.8' - const helmVersionCmd = `helm version --template '{{ .Version }}'` - const localHelmVersion = (await execCmdWithExitOnFailure(helmVersionCmd))[0].replace('^v', '') - - const helmOK = compareVersions.compare(localHelmVersion, requiredMinHelmVersion, '>=') - if (helmOK) { - return true - } else { - console.error( - `Error checking local helm version. Minimum Helm version required ${requiredMinHelmVersion}` - ) - process.exit(1) - } -} - -function rollingUpdateHelmVariables() { - return [ - `--set updateStrategy.validators.rollingUpdate.partition=${fetchEnvOrFallback( - envVar.VALIDATORS_ROLLING_UPDATE_PARTITION, - '0' - )}`, - `--set updateStrategy.secondaries.rollingUpdate.partition=${fetchEnvOrFallback( - envVar.SECONDARIES_ROLLING_UPDATE_PARTITION, - '0' - )}`, - `--set updateStrategy.proxy.rollingUpdate.partition=${fetchEnvOrFallback( - envVar.PROXY_ROLLING_UPDATE_PARTITION, - '0' - )}`, - `--set updateStrategy.tx_nodes.rollingUpdate.partition=${fetchEnvOrFallback( - envVar.TX_NODES_ROLLING_UPDATE_PARTITION, - '0' - )}`, - `--set updateStrategy.tx_nodes_private.rollingUpdate.partition=${fetchEnvOrFallback( - envVar.TX_NODES_PRIVATE_ROLLING_UPDATE_PARTITION, - '0' - )}`, - ] -} - -export async function saveHelmValuesFile( - celoEnv: string, - valueFilePath: string, - useExistingGenesis: boolean, - skipGenesisValue = false -) { - const genesisContent = useExistingGenesis - ? await getGenesisBlockFromGoogleStorage(celoEnv) - : generateGenesisFromEnv() - - const enodes = await getEnodesWithExternalIPAddresses(celoEnv) - - let valueFileContent = ` -staticnodes: - staticnodesBase64: ${Buffer.from(JSON.stringify(enodes)).toString('base64')} -` - if (!skipGenesisValue) { - valueFileContent += ` - genesis: - genesisFileBase64: ${Buffer.from(genesisContent).toString('base64')} -` - } - fs.writeFileSync(valueFilePath, valueFileContent) -} - -const celoBlockchainDir: string = path.join(os.tmpdir(), 'celo-blockchain-celotool') - -export async function createAndPushGenesis(celoEnv: string, reset: boolean, useMyCelo: boolean) { - let genesis: string = '' - try { - genesis = await getGenesisBlockFromGoogleStorage(celoEnv) - } catch { - console.debug(`Genesis file not found in GCP. Creating a new one`) - } - if (genesis === '' || reset === true) { - genesis = useMyCelo ? await generateMyCeloGenesis() : generateGenesisFromEnv() - } - // Upload the new genesis file to gcp - if (!isCelotoolHelmDryRun()) { - await uploadGenesisBlockToGoogleStorage(celoEnv, genesis) - } -} - -async function generateMyCeloGenesis(): Promise { - // Clean up the tmp dir - await spawnCmd('rm', ['-rf', celoBlockchainDir], { silent: true }) - fs.mkdirSync(celoBlockchainDir) - const gethTag = - fetchEnvOrFallback(envVar.GETH_MYCELO_COMMIT, '') !== '' - ? fetchEnv(envVar.GETH_MYCELO_COMMIT) - : fetchEnv(envVar.GETH_NODE_DOCKER_IMAGE_TAG) - const celoBlockchainVersion = gethTag.includes('.') ? `v${gethTag}` : gethTag - await checkoutGethRepo(celoBlockchainVersion, celoBlockchainDir) - await buildGethAll(celoBlockchainDir) - - // Generate genesis-config from template - const myceloBinary = path.join(celoBlockchainDir, 'build/bin/mycelo') - const myceloGenesisConfigArgs = [ - 'genesis-config', - '--template', - 'monorepo', - '--mnemonic', - fetchEnv(envVar.MNEMONIC), - '--validators', - fetchEnv(envVar.VALIDATORS), - '--dev.accounts', - fetchEnv(envVar.LOAD_TEST_CLIENTS), - '--blockperiod', - fetchEnv(envVar.BLOCK_TIME), - '--epoch', - fetchEnv(envVar.EPOCH), - '--blockgaslimit', - '20000000', - ] - await spawnCmdWithExitOnFailure(myceloBinary, myceloGenesisConfigArgs, { - silent: false, - cwd: celoBlockchainDir, - }) - - // TODO: Load config to customize migrations... - - // Generate genesis from config - - const myceloGenesisFromConfigArgs = [ - 'genesis-from-config', - celoBlockchainDir, - '--buildpath', - path.join(monorepoRoot, 'packages/protocol/build/contracts'), - ] - await spawnCmdWithExitOnFailure(myceloBinary, myceloGenesisFromConfigArgs, { - silent: false, - cwd: celoBlockchainDir, - }) - const genesisPath = path.join(celoBlockchainDir, 'genesis.json') - const genesisContent = fs.readFileSync(genesisPath).toString() - - // Clean up the tmp dir as it's no longer needed - await spawnCmd('rm', ['-rf', celoBlockchainDir], { silent: true }) - return genesisContent -} - -function useDefaultNetwork() { - return fetchEnv(envVar.KUBERNETES_CLUSTER_NAME) === 'celo-networks-dev' -} - -export function networkName(celoEnv: string) { - return useDefaultNetwork() ? 'default' : `${celoEnv}-network` -} diff --git a/packages/celotool/src/lib/interfaces/genesis-config.ts b/packages/celotool/src/lib/interfaces/genesis-config.ts deleted file mode 100644 index b59ca86b1..000000000 --- a/packages/celotool/src/lib/interfaces/genesis-config.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { AccountAndBalance, ConsensusType, Validator } from '../generate_utils' - -export interface GenesisConfig { - validators?: Validator[] - consensusType?: ConsensusType - initialAccounts?: AccountAndBalance[] - blockTime?: number - epoch?: number - lookbackwindow?: number - chainId?: number - requestTimeout?: number - enablePetersburg?: boolean - timestamp?: number - // Activation block numbers for Celo hard forks, null for never activating - churritoBlock?: number | null - donutBlock?: number | null - espressoBlock?: number | null - gingerbreadBlock?: number | null -} diff --git a/packages/celotool/src/lib/interfaces/geth-instance-config.ts b/packages/celotool/src/lib/interfaces/geth-instance-config.ts deleted file mode 100644 index bb72e7c13..000000000 --- a/packages/celotool/src/lib/interfaces/geth-instance-config.ts +++ /dev/null @@ -1,29 +0,0 @@ -import BigNumber from 'bignumber.js' - -export interface GethInstanceConfig { - name: string - validating?: boolean - replica?: boolean - validatingGasPrice?: number - syncmode: string - port: number - proxyport?: number - rpcport?: number - wsport?: number - lightserv?: boolean - gatewayFee?: BigNumber - privateKey?: string - minerValidator?: string - txFeeRecipient?: string - proxies?: Array - isProxied?: boolean - isProxy?: boolean - bootnodeEnode?: string - nodekey?: string - proxy?: string - proxiedValidatorAddress?: string - proxyAllowPrivateIp?: boolean - ethstats?: string - pid?: number - args?: string[] -} diff --git a/packages/celotool/src/lib/interfaces/geth-repository.ts b/packages/celotool/src/lib/interfaces/geth-repository.ts deleted file mode 100644 index 8107d4c24..000000000 --- a/packages/celotool/src/lib/interfaces/geth-repository.ts +++ /dev/null @@ -1,5 +0,0 @@ -export interface GethRepository { - path: string - remote?: boolean - branch?: string -} diff --git a/packages/celotool/src/lib/interfaces/geth-run-config.ts b/packages/celotool/src/lib/interfaces/geth-run-config.ts deleted file mode 100644 index 710e91ea5..000000000 --- a/packages/celotool/src/lib/interfaces/geth-run-config.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { GenesisConfig } from './genesis-config' -import { GethInstanceConfig } from './geth-instance-config' -import { GethRepository } from './geth-repository' - -export interface GethRunConfig { - // migration - migrate?: boolean - migrateTo?: number - migrationOverrides?: any - keepData?: boolean - // Whether to use the mycelo tool to generate the genesis.json - useMycelo?: boolean - // Skip compiling the smart contracts (e.g. during dev if they're already compiled and you want to save 10 seconds) - myceloSkipCompilingContracts?: boolean - // genesis config - genesisConfig?: GenesisConfig - // network - network: string - networkId: number - // where to run - runPath: string - verbosity?: number - repository?: GethRepository - // running instances - instances: GethInstanceConfig[] -} diff --git a/packages/celotool/src/lib/interfaces/mycelo-genesis-config.ts b/packages/celotool/src/lib/interfaces/mycelo-genesis-config.ts deleted file mode 100644 index d7abe9dd6..000000000 --- a/packages/celotool/src/lib/interfaces/mycelo-genesis-config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { GenesisConfig } from 'src/lib/interfaces/genesis-config' - -export interface MyceloGenesisConfig { - verbose: boolean - genesisConfig: GenesisConfig - numValidators: number // used in place of genesisConfig.validators - mnemonic: string - gethRepoPath: string - migrationOverrides?: any -} diff --git a/packages/celotool/src/lib/k8s-cluster/aks.ts b/packages/celotool/src/lib/k8s-cluster/aks.ts deleted file mode 100644 index 51b0c126d..000000000 --- a/packages/celotool/src/lib/k8s-cluster/aks.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { execCmd, execCmdWithExitOnFailure } from '../cmd-utils' -import { envVar, fetchEnv, fetchEnvOrFallback } from '../env-utils' -import { helmAddRepoAndUpdate, isCelotoolHelmDryRun } from '../helm_deploy' -import { outputIncludes } from '../utils' -import { BaseClusterConfig, BaseClusterManager, CloudProvider } from './base' - -export interface AksClusterConfig extends BaseClusterConfig { - tenantId: string - resourceGroup: string - subscriptionId: string - regionName: string -} - -export class AksClusterManager extends BaseClusterManager { - async switchToSubscription() { - let currentTenantId = null - try { - ;[currentTenantId] = await execCmd('az account show --query id -o tsv') - } catch (error) { - console.info('No azure account subscription currently set') - } - if (currentTenantId === null || currentTenantId.trim() !== this.clusterConfig.tenantId) { - await execCmdWithExitOnFailure( - `az account set --subscription ${this.clusterConfig.subscriptionId}` - ) - } - } - - async getAndSwitchToClusterContext() { - const kubeconfig = fetchEnvOrFallback(envVar.KUBECONFIG, '') - ? `--file ${fetchEnv(envVar.KUBECONFIG)}` - : '' - await execCmdWithExitOnFailure( - `az aks get-credentials --resource-group ${this.clusterConfig.resourceGroup} --name ${this.clusterConfig.clusterName} --subscription ${this.clusterConfig.subscriptionId} --overwrite-existing ${kubeconfig}` - ) - } - - async setupCluster(context?: string) { - await super.setupCluster(context) - await this.installAADPodIdentity() - } - - // installAADPodIdentity installs the resources necessary for AAD pod level identities - async installAADPodIdentity() { - // The helm chart maintained directly by AAD Pod Identity is not compatible with helm v2. - // Until we upgrade to helm v3, we rely on our own helm chart adapted from: - // https://raw.githubusercontent.com/Azure/aad-pod-identity/8a5f2ed5941496345592c42e1d6cbd12c32aeebf/deploy/infra/deployment-rbac.yaml - const aadPodIdentityExists = await outputIncludes( - `helm list -n default`, - `aad-pod-identity`, - `aad-pod-identity exists, skipping install` - ) - if (!aadPodIdentityExists) { - if (isCelotoolHelmDryRun()) { - console.info('Skipping aad-pod-identity deployment due to --helmdryrun') - } else { - console.info('Adding aad-pod-identity helm repository to local helm') - await helmAddRepoAndUpdate( - 'https://raw.githubusercontent.com/Azure/aad-pod-identity/master/charts', - 'aad-pod-identity' - ) - console.info('Installing aad-pod-identity') - await execCmdWithExitOnFailure( - `helm install aad-pod-identity aad-pod-identity/aad-pod-identity -n default` - ) - } - } - } - - get clusterConfig(): AksClusterConfig { - return this._clusterConfig as AksClusterConfig - } - - get kubernetesContextName(): string { - return this.clusterConfig.clusterName - } - - get cloudProvider(): CloudProvider { - return CloudProvider.AZURE - } -} diff --git a/packages/celotool/src/lib/k8s-cluster/base.ts b/packages/celotool/src/lib/k8s-cluster/base.ts deleted file mode 100644 index 0a18f49d6..000000000 --- a/packages/celotool/src/lib/k8s-cluster/base.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { createNamespaceIfNotExists } from '../cluster' -import { execCmd, execCmdWithExitOnFailure } from '../cmd-utils' -import { - installAndEnableMetricsDeps, - installCertManagerAndNginx, - isCelotoolHelmDryRun, -} from '../helm_deploy' - -export enum CloudProvider { - AZURE, - GCP, -} - -export interface BaseClusterConfig { - cloudProvider: CloudProvider - clusterName: string -} - -export abstract class BaseClusterManager { - protected _clusterConfig: BaseClusterConfig - private _celoEnv: string - - constructor(clusterConfig: BaseClusterConfig, celoEnv: string) { - this._clusterConfig = clusterConfig - this._celoEnv = celoEnv - } - - async switchToClusterContext(skipSetup: boolean, context?: string) { - const exists = await this.switchToClusterContextIfExists() - if (!exists) { - await this.getAndSwitchToClusterContext() - } - // Reset back to default namespace - await execCmdWithExitOnFailure(`kubectl config set-context --current --namespace default`) - if (!skipSetup) { - if (!isCelotoolHelmDryRun()) { - await this.setupCluster(context) - } else { - console.info(`Skipping cluster setup due to --helmdryrun`) - } - } - } - - /** - * This will set the current context to the listed cluster name. - * If a context with the cluster name does not exist, return false. - * @param clusterConfig - */ - async switchToClusterContextIfExists() { - await this.switchToSubscription() - - let currentContext = null - try { - ;[currentContext] = await execCmd('kubectl config current-context') - } catch (error) { - console.info('No context currently set') - } - - // We expect the context to be the cluster name. - if (currentContext === null || currentContext.trim() !== this.kubernetesContextName) { - const [existingContextsStr] = await execCmdWithExitOnFailure( - 'kubectl config get-contexts -o name' - ) - const existingContexts = existingContextsStr.trim().split('\n') - if (existingContexts.includes(this.clusterConfig.clusterName)) { - await execCmdWithExitOnFailure( - `kubectl config use-context ${this.clusterConfig.clusterName}` - ) - } else { - // If we don't already have the context, context set up is not complete. - // We would still need to retrieve credentials/contexts from the provider - return false - } - } - return true - } - - async setupCluster(context?: string) { - await createNamespaceIfNotExists(this.celoEnv) - if (!isCelotoolHelmDryRun()) { - console.info('Performing any cluster setup that needs to be done...') - - await installCertManagerAndNginx(this.celoEnv, this.clusterConfig) - await installAndEnableMetricsDeps(true, context, this.clusterConfig) - } - } - - abstract switchToSubscription(): Promise - abstract getAndSwitchToClusterContext(): Promise - - abstract get kubernetesContextName(): string - abstract get cloudProvider(): CloudProvider - - get clusterConfig(): BaseClusterConfig { - return this._clusterConfig - } - - get celoEnv(): string { - return this._celoEnv - } -} diff --git a/packages/celotool/src/lib/k8s-cluster/gcp.ts b/packages/celotool/src/lib/k8s-cluster/gcp.ts deleted file mode 100644 index bdce39367..000000000 --- a/packages/celotool/src/lib/k8s-cluster/gcp.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { execCmdWithExitOnFailure } from '../cmd-utils' -import { installGCPSSDStorageClass } from '../helm_deploy' -import { switchToGCPProject } from '../utils' -import { BaseClusterConfig, BaseClusterManager, CloudProvider } from './base' - -export interface GCPClusterConfig extends BaseClusterConfig { - projectName: string - zone: string -} - -export class GCPClusterManager extends BaseClusterManager { - async switchToSubscription() { - await switchToGCPProject(this.clusterConfig.projectName) - } - - async getAndSwitchToClusterContext() { - const { clusterName, projectName, zone } = this.clusterConfig - await execCmdWithExitOnFailure( - `gcloud container clusters get-credentials ${clusterName} --project ${projectName} --zone ${zone}` - ) - } - - async setupCluster(context?: string) { - await super.setupCluster(context) - await installGCPSSDStorageClass() - } - - get clusterConfig(): GCPClusterConfig { - return this._clusterConfig as GCPClusterConfig - } - - get kubernetesContextName(): string { - return `gke_${this.clusterConfig.projectName}_${this.clusterConfig.zone}_${this.clusterConfig.clusterName}` - } - - get cloudProvider(): CloudProvider { - return CloudProvider.GCP - } -} diff --git a/packages/celotool/src/lib/k8s-cluster/utils.ts b/packages/celotool/src/lib/k8s-cluster/utils.ts deleted file mode 100644 index a1584306a..000000000 --- a/packages/celotool/src/lib/k8s-cluster/utils.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { AksClusterConfig, AksClusterManager } from './aks' -import { BaseClusterConfig, BaseClusterManager, CloudProvider } from './base' -import { GCPClusterConfig, GCPClusterManager } from './gcp' - -const clusterManagerByCloudProvider: { - [key in CloudProvider]: (clusterConfig: BaseClusterConfig, celoEnv: string) => BaseClusterManager -} = { - [CloudProvider.AZURE]: (clusterConfig: BaseClusterConfig, celoEnv: string) => - new AksClusterManager(clusterConfig as AksClusterConfig, celoEnv), - [CloudProvider.GCP]: (clusterConfig: BaseClusterConfig, celoEnv: string) => - new GCPClusterManager(clusterConfig as GCPClusterConfig, celoEnv), -} - -export function getClusterManager( - cloudProvider: CloudProvider, - celoEnv: string, - clusterConfig: BaseClusterConfig -) { - return clusterManagerByCloudProvider[cloudProvider](clusterConfig, celoEnv) -} diff --git a/packages/celotool/src/lib/k8s-fullnode/aks.ts b/packages/celotool/src/lib/k8s-fullnode/aks.ts deleted file mode 100644 index a74156fb1..000000000 --- a/packages/celotool/src/lib/k8s-fullnode/aks.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { range } from 'lodash' -import { - deallocateStaticIP, - getAKSNodeResourceGroup, - registerStaticIPIfNotRegistered, - waitForStaticIPDetachment, -} from '../azure' -import { execCmdWithExitOnFailure } from '../cmd-utils' -import { AksClusterConfig } from '../k8s-cluster/aks' -import { deleteResource } from '../kubernetes' -import { BaseFullNodeDeployer, BaseFullNodeDeploymentConfig } from './base' - -export interface AksFullNodeDeploymentConfig extends BaseFullNodeDeploymentConfig { - clusterConfig: AksClusterConfig -} - -export class AksFullNodeDeployer extends BaseFullNodeDeployer { - async additionalHelmParameters() { - const staticIps = (await this.allocateStaticIPs()).join(',') - return [ - `--set azure=true`, - `--set geth.public_ip_per_node='{${staticIps}}'`, - // Azure has a special annotation to expose TCP and UDP on the same service. - // Only TCP needs to be specified in that case. - `--set geth.service_protocols='{TCP}'`, - // Fix for LES server panic-- don't serve any LES clients! - `--set geth.maxpeers=150`, - `--set geth.light.maxpeers=0`, - `--set geth.light.serve=0`, - `--set geth.use_gstorage_data=false`, - ] - } - - async allocateStaticIPs() { - console.info(`Creating static IPs on Azure for ${this.celoEnv}`) - const resourceGroup = await getAKSNodeResourceGroup(this.deploymentConfig.clusterConfig) - const { replicas } = this.deploymentConfig - // Deallocate static ip if we are scaling down the replica count - const existingStaticIPsCount = await this.getAzureStaticIPsCount(resourceGroup) - for (let i = existingStaticIPsCount - 1; i > replicas - 1; i--) { - await deleteResource(this.celoEnv, 'service', `${this.celoEnv}-fullnodes-${i}`, false) - await waitForStaticIPDetachment(`${this.staticIPNamePrefix}-${i}`, resourceGroup) - await deallocateStaticIP(`${this.staticIPNamePrefix}-${i}`, resourceGroup) - } - - const addresses = await Promise.all( - range(replicas).map((i) => - registerStaticIPIfNotRegistered(`${this.staticIPNamePrefix}-${i}`, resourceGroup) - ) - ) - - return addresses - } - - async getAzureStaticIPsCount(resourceGroup: string) { - const [staticIPsCount] = await execCmdWithExitOnFailure( - `az network public-ip list --resource-group ${resourceGroup} --query "[?contains(name,'${this.staticIPNamePrefix}')].{Name:name, IPAddress:ipAddress}" -o tsv | wc -l` - ) - return parseInt(staticIPsCount.trim(), 10) - } - - async deallocateAllIPs() { - console.info(`Deallocating static IPs on Azure for ${this.celoEnv}`) - - const resourceGroup = await getAKSNodeResourceGroup(this.deploymentConfig.clusterConfig) - const replicaCount = await this.getAzureStaticIPsCount(resourceGroup) - - await this.waitForAllStaticIPDetachment() - - await Promise.all( - range(replicaCount).map((i) => - deallocateStaticIP(`${this.staticIPNamePrefix}-${i}`, resourceGroup) - ) - ) - } - - async waitForAllStaticIPDetachment() { - const resourceGroup = await getAKSNodeResourceGroup(this.deploymentConfig.clusterConfig) - - await Promise.all( - range(this.deploymentConfig.replicas).map((i) => - waitForStaticIPDetachment(`${this.staticIPNamePrefix}-${i}`, resourceGroup) - ) - ) - } - - async getFullNodeIP(index: number, resourceGroup?: string): Promise { - resourceGroup = - resourceGroup || (await getAKSNodeResourceGroup(this.deploymentConfig.clusterConfig)) - return registerStaticIPIfNotRegistered(`${this.staticIPNamePrefix}-${index}`, resourceGroup) - } - - get deploymentConfig(): AksFullNodeDeploymentConfig { - return this._deploymentConfig as AksFullNodeDeploymentConfig - } -} diff --git a/packages/celotool/src/lib/k8s-fullnode/base-nodeport.ts b/packages/celotool/src/lib/k8s-fullnode/base-nodeport.ts deleted file mode 100644 index b7ac98a17..000000000 --- a/packages/celotool/src/lib/k8s-fullnode/base-nodeport.ts +++ /dev/null @@ -1,154 +0,0 @@ -import { range } from 'lodash' -import { getAllUsedNodePorts, getService } from '../kubernetes' -import { BaseFullNodeDeployer, BaseFullNodeDeploymentConfig } from './base' - -const NODE_PORT_MIN = 30000 -const NODE_PORT_MAX = 32767 - -export abstract class BaseNodePortFullNodeDeployer extends BaseFullNodeDeployer { - async additionalHelmParameters() { - const existingNodePortSet = await this.getExistingNodePortSet() - const newNodePortForEachFullNode = await this.getNodePortForEachFullNode() - const newNodePortSet = new Set(newNodePortForEachFullNode) - // Essentially existingNodePortSet - newNodePortForEachFullNode - const nodePortsToRemove = new Set( - Array.from(existingNodePortSet).filter((existing) => !newNodePortSet.has(existing)) - ) - // Ensure all the new node ports have ingress rules set - await this.setIngressRulesTCPAndUDP(newNodePortForEachFullNode, true) - // Remove any removed node port ingress rules - await this.setIngressRulesTCPAndUDP(Array.from(nodePortsToRemove), false) - - const nodePortPerFullNodeStrs = newNodePortForEachFullNode.map( - (nodePort: number, index: number) => - `--set geth.service_node_port_per_full_node[${index}]=${nodePort}` - ) - return [...nodePortPerFullNodeStrs, `--set geth.service_type=NodePort`] - } - - async getNodePortForEachFullNode() { - // Get all node ports that are currently used on the entire cluster - const allUsedNodePorts: number[] = await getAllUsedNodePorts() - // Get the service for each full node. An element will be undefined if does not exist - const serviceForEachFullNode: any[] = await this.getServiceForEachFullNode() - - const NO_NODE_PORT = -1 - // Get the node port for each existing full node service. If none has been - // assigned, give `NO_KNOWN_NODE_PORT` - const nodePortForEachFullNode: number[] = serviceForEachFullNode.map((service: any) => { - if (!service) { - return NO_NODE_PORT - } - return service.spec.ports.reduce((existingNodePort: number, portsSpec: any) => { - if (!portsSpec.nodePort) { - return existingNodePort - } - if (existingNodePort !== NO_NODE_PORT && existingNodePort !== portsSpec.nodePort) { - throw Error( - `Expected all nodePorts to be the same in service, got ${existingNodePort} !== ${portsSpec.nodePort}` - ) - } - return portsSpec.nodePort - }, NO_NODE_PORT) - }) - - let potentialPort = NODE_PORT_MIN - let allUsedNodePortsIndex = 0 - // Assign node port to services that do not have one yet. Do so in a way to - // not assign a node port that has been assigned to another service on the - // cluster, and keep newly assigned node ports as close to the minPort as - // possible. Doing so makes reasoning about node ports and port ranges way easier. - for (let i = 0; i < nodePortForEachFullNode.length; i++) { - const nodePort = nodePortForEachFullNode[i] - if (nodePort === NO_NODE_PORT) { - for (; allUsedNodePortsIndex < allUsedNodePorts.length; allUsedNodePortsIndex++) { - if (potentialPort > NODE_PORT_MAX) { - throw Error(`No available node ports`) - } - const usedPort = allUsedNodePorts[allUsedNodePortsIndex] - if (potentialPort < usedPort) { - break - } - // Try the next port on the next iteration - potentialPort = usedPort + 1 - } - // Assign the port - nodePortForEachFullNode[i] = potentialPort - // Add the newly assigned port to allUsedNodePorts - allUsedNodePorts.splice(allUsedNodePortsIndex, 0, potentialPort) - // Increment potential port for a potential subsequent NodePort assignment - potentialPort++ - } - } - return nodePortForEachFullNode - } - - /** - * Not needed for NodePort services. Instead, shows a message to remove any - * now-unused ports from the security group whitelist - */ - async deallocateAllIPs() { - // Do nothing - } - - /** - * Returns an array with each element as the corresponding full node's service. - * An element will be undefined if the service doesn't exist. - */ - getServiceForEachFullNode() { - const replicas = this.deploymentConfig.replicas - return Promise.all( - range(replicas).map(async (i: number) => - getService(`${this.celoEnv}-fullnodes-${i}`, this.kubeNamespace) - ) - ) - } - - /** - * Returns an array of all services that currently exist for full nodes. - * Does so using a selector, and has no guarantees about the order of the services. - */ - async getExistingFullNodeServices() { - const response = await getService( - `--selector=component=celo-fullnode-protocol-traffic`, - this.kubeNamespace - ) - return response.items - } - - /** - * Looks at the existing full node services and returns which nodePorts are currently used. - */ - async getExistingNodePortSet(): Promise> { - const serviceForEachFullNode = await this.getExistingFullNodeServices() - return serviceForEachFullNode.reduce((set: Set, service: any) => { - // If there is no service for a full node, it is undefined. Just ignore - if (!service) { - return set - } - for (const portSpec of service.spec.ports) { - if (portSpec.nodePort) { - set.add(portSpec.nodePort) - } - } - return set - }, new Set()) - } - - async getFullNodeIP(_index: number): Promise { - throw Error('Not supported for NodePort full nodes') - } - - /** - * Determines if a given port number is a valid node port. - */ - isNodePort(portNumber: number): boolean { - return portNumber >= NODE_PORT_MIN && portNumber <= NODE_PORT_MAX - } - - abstract setIngressRulesTCPAndUDP(nodePorts: number[], authorize: boolean): Promise - - get deploymentConfig(): BaseFullNodeDeploymentConfig { - return this._deploymentConfig - } -} diff --git a/packages/celotool/src/lib/k8s-fullnode/base.ts b/packages/celotool/src/lib/k8s-fullnode/base.ts deleted file mode 100644 index cc107ea08..000000000 --- a/packages/celotool/src/lib/k8s-fullnode/base.ts +++ /dev/null @@ -1,191 +0,0 @@ -import fs from 'fs' -import { range } from 'lodash' -import { readableContext } from 'src/lib/context-utils' -import { createNamespaceIfNotExists } from '../cluster' -import { envVar, fetchEnv, fetchEnvOrFallback } from '../env-utils' -import { generatePrivateKeyWithDerivations, privateKeyToPublicKey } from '../generate_utils' -import { - deletePersistentVolumeClaims, - installGenericHelmChart, - isCelotoolHelmDryRun, - removeGenericHelmChart, - upgradeGenericHelmChart, -} from '../helm_deploy' -import { scaleResource } from '../kubernetes' - -const helmChartPath = 'oci://us-west1-docker.pkg.dev/devopsre/clabs-public-oci/celo-fullnode' -const chartVersion = '0.2.0' - -export interface NodeKeyGenerationInfo { - mnemonic: string - // A derivation index to apply to the mnemonic. - // Each full node will then have its node key derived like: - // mnemonic.derive(derivationIndex).derive(fullNodeIndex) - derivationIndex: number -} - -export interface BaseFullNodeDeploymentConfig { - diskSizeGb: number - replicas: number - rollingUpdatePartition: number - rpcApis: string - gcMode: string - useGstoreData: string - wsPort: number - // If undefined, node keys will not be predetermined and will be random - nodeKeyGenerationInfo?: NodeKeyGenerationInfo -} - -export abstract class BaseFullNodeDeployer { - protected _deploymentConfig: BaseFullNodeDeploymentConfig - private _celoEnv: string - - constructor(deploymentConfig: BaseFullNodeDeploymentConfig, celoEnv: string) { - this._deploymentConfig = deploymentConfig - this._celoEnv = celoEnv - } - - // If the node key is generated, then a promise containing the enodes is returned. - // Otherwise, the enode cannot be calculated deterministically so a Promise is returned. - async installChart(context: string): Promise { - await createNamespaceIfNotExists(this.kubeNamespace) - - await installGenericHelmChart({ - namespace: this.kubeNamespace, - releaseName: this.releaseName, - chartDir: helmChartPath, - parameters: await this.helmParameters(context), - chartVersion, - buildDependencies: false, - }) - - if (this._deploymentConfig.nodeKeyGenerationInfo) { - return this.getEnodes() - } - } - - // If the node key is generated, then a promise containing the enodes is returned. - // Otherwise, the enode cannot be calculated deterministically so a Promise is returned. - async upgradeChart(context: string, reset: boolean): Promise { - if (isCelotoolHelmDryRun()) { - await upgradeGenericHelmChart({ - namespace: this.kubeNamespace, - releaseName: this.releaseName, - chartDir: helmChartPath, - parameters: await this.helmParameters(context), - chartVersion, - buildDependencies: false, - }) - } else { - if (reset) { - await scaleResource(this.celoEnv, 'StatefulSet', `${this.celoEnv}-fullnodes`, 0) - await deletePersistentVolumeClaims(this.celoEnv, ['celo-fullnode']) - } - - await upgradeGenericHelmChart({ - namespace: this.kubeNamespace, - releaseName: this.releaseName, - chartDir: helmChartPath, - parameters: await this.helmParameters(context), - chartVersion, - buildDependencies: false, - }) - - await scaleResource( - this.celoEnv, - 'StatefulSet', - `${this.celoEnv}-fullnodes`, - this._deploymentConfig.replicas - ) - } - if (this._deploymentConfig.nodeKeyGenerationInfo) { - return this.getEnodes() - } - } - - async removeChart() { - await removeGenericHelmChart(this.releaseName, this.kubeNamespace) - await deletePersistentVolumeClaims(this.celoEnv, ['celo-fullnode']) - await this.deallocateAllIPs() - } - - async helmParameters(context: string) { - let nodeKeys: string[] | undefined - if (this._deploymentConfig.nodeKeyGenerationInfo) { - nodeKeys = range(this._deploymentConfig.replicas).map((index: number) => - this.getPrivateKey(index) - ) - } - - const rpcApis = this._deploymentConfig.rpcApis - ? this._deploymentConfig.rpcApis - : 'eth,net,rpc,web3' - const gcMode = this._deploymentConfig.gcMode ? this._deploymentConfig.gcMode : 'full' - const customValuesFile = `${helmChartPath}/${this._celoEnv}-${readableContext( - context - )}-values.yaml` - return [ - `--set namespace=${this.kubeNamespace}`, - `--set replicaCount=${this._deploymentConfig.replicas}`, - `--set geth.updateStrategy.rollingUpdate.partition=${this._deploymentConfig.rollingUpdatePartition}`, - `--set storage.size=${this._deploymentConfig.diskSizeGb}Gi`, - `--set geth.expose_rpc_externally=false`, - `--set geth.gcmode=${gcMode}`, - `--set geth.image.repository=${fetchEnv(envVar.GETH_NODE_DOCKER_IMAGE_REPOSITORY)}`, - `--set geth.image.tag=${fetchEnv(envVar.GETH_NODE_DOCKER_IMAGE_TAG)}`, - `--set-string geth.rpc_apis='${rpcApis.split(',').join('\\,')}'`, - `--set geth.metrics=${fetchEnvOrFallback(envVar.GETH_ENABLE_METRICS, 'false')}`, - `--set genesis.networkId=${fetchEnv(envVar.NETWORK_ID)}`, - `--set genesis.network=${this.celoEnv}`, - `--set geth.use_gstorage_data=${this._deploymentConfig.useGstoreData}`, - `--set geth.ws_port=${this._deploymentConfig.wsPort}`, - `--set geth.gstorage_data_bucket=${fetchEnvOrFallback('GSTORAGE_DATA_BUCKET', '')}`, - ...(await this.additionalHelmParameters()), - nodeKeys ? `--set geth.node_keys='{${nodeKeys.join(',')}}'` : '', - fs.existsSync(customValuesFile) ? `-f ${customValuesFile}` : '', - ] - } - - async getEnodes() { - return Promise.all( - range(this._deploymentConfig.replicas).map(async (index: number) => { - const publicKey = privateKeyToPublicKey(this.getPrivateKey(index)) - const ip = await this.getFullNodeIP(index) - // Assumes 30303 is the port - return `enode://${publicKey}@${ip}:30303` - }) - ) - } - - getPrivateKey(index: number) { - if (!this._deploymentConfig.nodeKeyGenerationInfo) { - throw Error( - 'The deployment config property nodeKeyGenerationInfo must be defined to get a full node private key' - ) - } - return generatePrivateKeyWithDerivations( - this._deploymentConfig.nodeKeyGenerationInfo!.mnemonic, - [this._deploymentConfig.nodeKeyGenerationInfo!.derivationIndex, index] - ) - } - - abstract additionalHelmParameters(): Promise - abstract deallocateAllIPs(): Promise - abstract getFullNodeIP(index: number): Promise - - get releaseName() { - return `${this.celoEnv}-fullnodes` - } - - get kubeNamespace() { - return this.celoEnv - } - - get staticIPNamePrefix() { - return `${this.celoEnv}-fullnodes` - } - - get celoEnv(): string { - return this._celoEnv - } -} diff --git a/packages/celotool/src/lib/k8s-fullnode/gcp.ts b/packages/celotool/src/lib/k8s-fullnode/gcp.ts deleted file mode 100644 index 26c3c65d0..000000000 --- a/packages/celotool/src/lib/k8s-fullnode/gcp.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { concurrentMap } from '@celo/base' -import { range } from 'lodash' -import { execCmd } from '../cmd-utils' -import { deleteIPAddress, registerIPAddress, retrieveIPAddress } from '../helm_deploy' -import { GCPClusterConfig } from '../k8s-cluster/gcp' -import { BaseFullNodeDeployer, BaseFullNodeDeploymentConfig } from './base' - -export interface GCPFullNodeDeploymentConfig extends BaseFullNodeDeploymentConfig { - clusterConfig: GCPClusterConfig - createNEG: boolean -} - -export class GCPFullNodeDeployer extends BaseFullNodeDeployer { - async additionalHelmParameters() { - const staticIps = (await this.allocateStaticIPs()).join(',') - return [ - `--set gcp=true`, - `--set storage.storageClass=ssd`, - `--set geth.public_ip_per_node='{${staticIps}}'`, - `--set geth.create_network_endpoint_group=${this.deploymentConfig.createNEG}`, - `--set geth.flags='--txpool.nolocals'`, - ] - } - - async allocateStaticIPs() { - await concurrentMap(5, range(this.deploymentConfig.replicas), (i) => - registerIPAddress(this.getIPAddressName(i), this.deploymentConfig.clusterConfig.zone) - ) - await Promise.all([this.deallocateIPsWithNames(await this.ipAddressNamesToDeallocate())]) - return Promise.all( - range(this.deploymentConfig.replicas).map((index: number) => this.getFullNodeIP(index)) - ) - } - - async getFullNodeIP(index: number): Promise { - return retrieveIPAddress(this.getIPAddressName(index), this.deploymentConfig.clusterConfig.zone) - } - - async ipAddressNamesToDeallocate(intendedReplicas: number = this.deploymentConfig.replicas) { - const [allMatchesRaw] = await execCmd( - `gcloud compute addresses list --filter="name~'${this.ipAddressPrefix}-[0-9]+'" --format json` - ) - const allMatches = JSON.parse(allMatchesRaw) - const getReplicaFromIPName = (ipName: string) => { - const regex = new RegExp(`${this.ipAddressPrefix}-([0-9]+)`, 'g') - const matches = regex.exec(ipName) - if (matches == null) { - return null - } - return parseInt(matches[1], 10) - } - return allMatches - .filter((ipDescription: any) => { - const replica = getReplicaFromIPName(ipDescription.name) - return replica != null && replica >= intendedReplicas - }) - .map((ipDescription: any) => ipDescription.name) - } - - async deallocateIPsWithNames(names: string[]) { - await Promise.all( - names.map((name: string) => deleteIPAddress(name, this.deploymentConfig.clusterConfig.zone)) - ) - } - - async deallocateAllIPs() { - const ipNamesToDeallocate = await this.ipAddressNamesToDeallocate(0) - await this.deallocateIPsWithNames(ipNamesToDeallocate) - } - - getIPAddressName(index: number) { - return `${this.ipAddressPrefix}-${index}` - } - - get ipAddressPrefix() { - return `${this.celoEnv}-${this.deploymentConfig.clusterConfig.clusterName}` - } - - get deploymentConfig(): GCPFullNodeDeploymentConfig { - return this._deploymentConfig as GCPFullNodeDeploymentConfig - } -} diff --git a/packages/celotool/src/lib/k8s-fullnode/utils.ts b/packages/celotool/src/lib/k8s-fullnode/utils.ts deleted file mode 100644 index 67d6e839d..000000000 --- a/packages/celotool/src/lib/k8s-fullnode/utils.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { CloudProvider } from '../k8s-cluster/base' -import { AksFullNodeDeployer, AksFullNodeDeploymentConfig } from './aks' -import { BaseFullNodeDeployer, BaseFullNodeDeploymentConfig } from './base' -import { GCPFullNodeDeployer, GCPFullNodeDeploymentConfig } from './gcp' - -const fullNodeDeployerByCloudProvider: { - [key in CloudProvider]: ( - deploymentConfig: BaseFullNodeDeploymentConfig, - celoEnv: string - ) => BaseFullNodeDeployer -} = { - [CloudProvider.AZURE]: (deploymentConfig: BaseFullNodeDeploymentConfig, celoEnv: string) => - new AksFullNodeDeployer(deploymentConfig as AksFullNodeDeploymentConfig, celoEnv), - [CloudProvider.GCP]: (deploymentConfig: BaseFullNodeDeploymentConfig, celoEnv: string) => - new GCPFullNodeDeployer(deploymentConfig as GCPFullNodeDeploymentConfig, celoEnv), -} - -export function getFullNodeDeployer( - cloudProvider: CloudProvider, - celoEnv: string, - deploymentConfig: BaseFullNodeDeploymentConfig -) { - return fullNodeDeployerByCloudProvider[cloudProvider](deploymentConfig, celoEnv) -} diff --git a/packages/celotool/src/lib/k8s-oracle/aks-hsm.ts b/packages/celotool/src/lib/k8s-oracle/aks-hsm.ts deleted file mode 100644 index b634b0c42..000000000 --- a/packages/celotool/src/lib/k8s-oracle/aks-hsm.ts +++ /dev/null @@ -1,179 +0,0 @@ -import { - assignRoleIdempotent, - createIdentityIdempotent, - deleteIdentity, - getAKSManagedServiceIdentityObjectId, - getAKSServicePrincipalObjectId, - getIdentity, -} from '../azure' -import { execCmdWithExitOnFailure } from '../cmd-utils' -import { AksClusterConfig } from '../k8s-cluster/aks' -import { BaseOracleDeploymentConfig, OracleIdentity } from './base' -import { RbacOracleDeployer } from './rbac' - -/** - * Contains information needed when using Azure HSM signing - */ -export interface AksHsmOracleIdentity extends OracleIdentity { - keyVaultName: string - resourceGroup: string -} - -export interface AksHsmOracleDeploymentConfig extends BaseOracleDeploymentConfig { - clusterConfig: AksClusterConfig - identities: AksHsmOracleIdentity[] -} - -/** - * AksHsmOracleDeployer manages deployments for HSM-based oracles on AKS - */ -export class AksHsmOracleDeployer extends RbacOracleDeployer { - // Explicitly specify this so we enforce AksHsmOracleDeploymentConfig - constructor(deploymentConfig: AksHsmOracleDeploymentConfig, celoEnv: string) { - super(deploymentConfig, celoEnv) - } - - async removeChart() { - await super.removeChart() - for (const identity of this.deploymentConfig.identities) { - await this.deleteAzureHsmIdentity(identity) - } - } - - async helmParameters() { - return [ - ...(await super.helmParameters()), - `--set kube.cloudProvider=azure`, - `--set oracle.azureHsm.initTryCount=5`, - `--set oracle.azureHsm.initMaxRetryBackoffMs=30000`, - `--set oracle.walletType=AZURE_HSM`, - ] - } - - async oracleIdentityHelmParameters() { - let params = await super.oracleIdentityHelmParameters() - for (let i = 0; i < this.replicas; i++) { - const oracleIdentity = this.deploymentConfig.identities[i] - const prefix = `--set oracle.identities[${i}]` - const azureIdentity = await this.createOracleAzureIdentityIdempotent(oracleIdentity) - params = params.concat([ - `${prefix}.azure.id=${azureIdentity.id}`, - `${prefix}.azure.clientId=${azureIdentity.clientId}`, - `${prefix}.azure.keyVaultName=${oracleIdentity.keyVaultName}`, - ]) - } - return params - } - - /** - * Creates an Azure identity for a specific oracle identity with the - * appropriate permissions to use its HSM. - * Idempotent. - */ - async createOracleAzureIdentityIdempotent(oracleHsmIdentity: AksHsmOracleIdentity) { - const identity = await createIdentityIdempotent( - this.clusterConfig, - this.azureHsmIdentityName(oracleHsmIdentity) - ) - // We want to grant the identity for the cluster permission to manage the oracle identity. - // Get the correct object ID depending on the cluster configuration, either - // the service principal or the managed service identity. - // See https://github.com/Azure/aad-pod-identity/blob/b547ba86ab9b16d238db8a714aaec59a046afdc5/docs/readmes/README.role-assignment.md#obtaining-the-id-of-the-managed-identity--service-principal - let assigneeObjectId = await getAKSServicePrincipalObjectId(this.clusterConfig) - let assigneePrincipalType = 'ServicePrincipal' - if (!assigneeObjectId) { - assigneeObjectId = await getAKSManagedServiceIdentityObjectId(this.clusterConfig) - assigneePrincipalType = 'MSI' - } - await assignRoleIdempotent( - assigneeObjectId, - assigneePrincipalType, - identity.id, - 'Managed Identity Operator' - ) - // Allow the oracle identity to access the correct key vault - await this.setOracleKeyVaultPolicyIdempotent(oracleHsmIdentity, identity) - return identity - } - - /** - * Ensures an Azure identity has the appropriate permissions to use its HSM - * via a key vault policy. - * Idempotent. - */ - async setOracleKeyVaultPolicyIdempotent( - oracleHsmIdentity: AksHsmOracleIdentity, - azureIdentity: any - ) { - const keyPermissions = ['get', 'list', 'sign'] - const keyVaultResourceGroup = oracleHsmIdentity.resourceGroup - const [keyVaultPoliciesStr] = await execCmdWithExitOnFailure( - `az keyvault show --name ${ - oracleHsmIdentity.keyVaultName - } -g ${keyVaultResourceGroup} --query "properties.accessPolicies[?objectId == '${ - azureIdentity.principalId - }' && sort(permissions.keys) == [${keyPermissions.map((perm) => `'${perm}'`).join(', ')}]]"` - ) - const keyVaultPolicies = JSON.parse(keyVaultPoliciesStr) - if (keyVaultPolicies.length) { - console.info( - `Skipping setting key permissions, ${keyPermissions.join(' ')} already set for vault ${ - oracleHsmIdentity.keyVaultName - } and identity objectId ${azureIdentity.principalId}` - ) - return - } - console.info( - `Setting key permissions ${keyPermissions.join(' ')} for vault ${ - oracleHsmIdentity.keyVaultName - } and identity objectId ${azureIdentity.principalId}` - ) - return execCmdWithExitOnFailure( - `az keyvault set-policy --name ${ - oracleHsmIdentity.keyVaultName - } --key-permissions ${keyPermissions.join(' ')} --object-id ${ - azureIdentity.principalId - } -g ${keyVaultResourceGroup}` - ) - } - - /** - * Deletes the key vault policy and the oracle's managed identity - */ - async deleteAzureHsmIdentity(oracleHsmIdentity: AksHsmOracleIdentity) { - const identityName = this.azureHsmIdentityName(oracleHsmIdentity) - console.info(`Deleting Azure identity ${identityName}`) - await this.deleteOracleKeyVaultPolicy(oracleHsmIdentity) - return deleteIdentity(this.clusterConfig, identityName) - } - - /** - * Deletes the key vault policy that allows an Azure managed identity to use - * its HSM. - */ - async deleteOracleKeyVaultPolicy(oracleHsmIdentity: AksHsmOracleIdentity) { - const azureIdentity = await getIdentity( - this.clusterConfig, - this.azureHsmIdentityName(oracleHsmIdentity) - ) - return execCmdWithExitOnFailure( - `az keyvault delete-policy --name ${oracleHsmIdentity.keyVaultName} --object-id ${azureIdentity.principalId} -g ${oracleHsmIdentity.resourceGroup}` - ) - } - - /** - * @return the intended name of an azure identity - */ - azureHsmIdentityName(identity: AksHsmOracleIdentity) { - // Max length from https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/resource-name-rules#microsoftmanagedidentity - return `${identity.keyVaultName}-${identity.currencyPair}-${identity.address}`.substring(0, 128) - } - - get deploymentConfig(): AksHsmOracleDeploymentConfig { - return this._deploymentConfig as AksHsmOracleDeploymentConfig - } - - get clusterConfig(): AksClusterConfig { - return this.deploymentConfig.clusterConfig - } -} diff --git a/packages/celotool/src/lib/k8s-oracle/base.ts b/packages/celotool/src/lib/k8s-oracle/base.ts deleted file mode 100644 index e6ef12c8a..000000000 --- a/packages/celotool/src/lib/k8s-oracle/base.ts +++ /dev/null @@ -1,132 +0,0 @@ -import { - getFornoUrl, - getFornoWebSocketUrl, - getLightNodeHttpRpcInternalUrl, - getLightNodeWebSocketRpcInternalUrl, -} from 'src/lib/endpoints' -import { envVar, fetchEnv, fetchEnvOrFallback } from 'src/lib/env-utils' -import { - installGenericHelmChart, - removeGenericHelmChart, - upgradeGenericHelmChart, -} from 'src/lib/helm_deploy' - -const helmChartPath = '../helm-charts/oracle' - -export type CurrencyPair = 'CELOUSD' | 'CELOEUR' | 'CELOBTC' - -/** - * Represents the identity of a single oracle - */ -export interface OracleIdentity { - address: string - currencyPair: CurrencyPair -} - -export interface BaseOracleDeploymentConfig { - context: string - currencyPair: CurrencyPair - identities: OracleIdentity[] - useForno: boolean -} - -export abstract class BaseOracleDeployer { - protected _deploymentConfig: BaseOracleDeploymentConfig - private _celoEnv: string - - constructor(deploymentConfig: BaseOracleDeploymentConfig, celoEnv: string) { - this._deploymentConfig = deploymentConfig - this._celoEnv = celoEnv - } - - async installChart() { - return installGenericHelmChart({ - namespace: this.celoEnv, - releaseName: this.releaseName, - chartDir: helmChartPath, - parameters: await this.helmParameters(), - buildDependencies: true, - valuesOverrideFile: `${this.currencyPair}.yaml`, - }) - } - - async upgradeChart() { - return upgradeGenericHelmChart({ - namespace: this.celoEnv, - releaseName: this.releaseName, - chartDir: helmChartPath, - parameters: await this.helmParameters(), - buildDependencies: true, - valuesOverrideFile: `${this.currencyPair}.yaml`, - }) - } - - async removeChart() { - await removeGenericHelmChart(this.releaseName, this.celoEnv) - } - - async helmParameters() { - const httpRpcProviderUrl = this.deploymentConfig.useForno - ? getFornoUrl(this.celoEnv) - : getLightNodeHttpRpcInternalUrl(this.celoEnv) - const wsRpcProviderUrl = this.deploymentConfig.useForno - ? getFornoWebSocketUrl(this.celoEnv) - : getLightNodeWebSocketRpcInternalUrl(this.celoEnv) - return [ - `--set-literal oracle.api_keys=${fetchEnv(envVar.ORACLE_FX_ADAPTERS_API_KEYS)}`, - `--set environment.name=${this.celoEnv}`, - `--set image.repository=${fetchEnv(envVar.ORACLE_DOCKER_IMAGE_REPOSITORY)}`, - `--set image.tag=${fetchEnv(envVar.ORACLE_DOCKER_IMAGE_TAG)}`, - `--set oracle.replicas=${this.replicas}`, - `--set oracle.rpcProviderUrls.http=${httpRpcProviderUrl}`, - `--set oracle.rpcProviderUrls.ws=${wsRpcProviderUrl}`, - `--set-string oracle.unusedOracleAddresses='${fetchEnvOrFallback( - envVar.ORACLE_UNUSED_ORACLE_ADDRESSES, - '' - ) - .split(',') - .join('\\,')}'`, - ].concat(await this.oracleIdentityHelmParameters()) - } - - /** - * Returns an array of helm command line parameters for the oracle identities. - */ - async oracleIdentityHelmParameters() { - const params: string[] = [] - for (let i = 0; i < this.replicas; i++) { - const oracleIdentity = this.deploymentConfig.identities[i] - const prefix = `--set oracle.identities[${i}]` - params.push(`${prefix}.address=${oracleIdentity.address}`) - } - return params - } - - get deploymentConfig() { - return this._deploymentConfig - } - - get releaseName() { - return `${this.celoEnv}-${this.currencyPair.toLocaleLowerCase()}-oracle` - } - - get kubeNamespace() { - return this.celoEnv - } - - get celoEnv(): string { - return this._celoEnv - } - - get replicas(): number { - return this.deploymentConfig.identities.length - } - - get context(): string { - return this.deploymentConfig.context - } - - get currencyPair(): CurrencyPair { - return this.deploymentConfig.currencyPair - } -} diff --git a/packages/celotool/src/lib/k8s-oracle/pkey.ts b/packages/celotool/src/lib/k8s-oracle/pkey.ts deleted file mode 100644 index 1b9e0cae7..000000000 --- a/packages/celotool/src/lib/k8s-oracle/pkey.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { BaseOracleDeployer, BaseOracleDeploymentConfig, OracleIdentity } from './base' - -export interface PrivateKeyOracleIdentity extends OracleIdentity { - privateKey: string -} - -export interface PrivateKeyOracleDeploymentConfig extends BaseOracleDeploymentConfig { - identities: PrivateKeyOracleIdentity[] -} - -/** - * PrivateKeyOracleDeployer cloud-agnostically manages deployments for oracles - * that are using in-memory signing via private keys - */ -export class PrivateKeyOracleDeployer extends BaseOracleDeployer { - constructor(deploymentConfig: PrivateKeyOracleDeploymentConfig, celoEnv: string) { - super(deploymentConfig, celoEnv) - } - - async helmParameters() { - return [...(await super.helmParameters()), `--set oracle.walletType=PRIVATE_KEY`] - } - - async oracleIdentityHelmParameters() { - const params: string[] = await super.oracleIdentityHelmParameters() - for (let i = 0; i < this.replicas; i++) { - const oracleIdentity = this.deploymentConfig.identities[i] - const prefix = `--set oracle.identities[${i}]` - params.push(`${prefix}.privateKey=${oracleIdentity.privateKey}`) - } - return params - } - - get deploymentConfig(): PrivateKeyOracleDeploymentConfig { - return this._deploymentConfig as PrivateKeyOracleDeploymentConfig - } -} diff --git a/packages/celotool/src/lib/k8s-oracle/rbac.ts b/packages/celotool/src/lib/k8s-oracle/rbac.ts deleted file mode 100644 index 7d45f97b4..000000000 --- a/packages/celotool/src/lib/k8s-oracle/rbac.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { - installGenericHelmChart, - removeGenericHelmChart, - upgradeGenericHelmChart, -} from 'src/lib/helm_deploy' -import { BaseOracleDeployer } from './base' - -// Oracle RBAC------ -// We need the oracle pods to be able to change their label to accommodate -// limitations in aad-pod-identity & statefulsets (see https://github.com/Azure/aad-pod-identity/issues/237#issuecomment-611672987) -// To do this, we use an auth token that we get using the resources in the `oracle-rbac` chart - -const rbacHelmChartPath = '../helm-charts/oracle-rbac' - -/** - * RbacOracleDeployer cloud-agnostically manages deployments for oracles - * whose pods must change their metadata in order to accomodate limitations - * in pod identity solutions (like Azure's aad-pod-identity). - * This will create a k8s service account for each oracle pod that can modify - * pod metadata, and will ensure each SA's credentials make their way to the helm chart. - */ -export abstract class RbacOracleDeployer extends BaseOracleDeployer { - async installChart() { - await installGenericHelmChart({ - namespace: this.celoEnv, - releaseName: this.rbacReleaseName(), - chartDir: rbacHelmChartPath, - parameters: this.rbacHelmParameters(), - }) - return super.installChart() - } - - async upgradeChart() { - await upgradeGenericHelmChart({ - namespace: this.celoEnv, - releaseName: this.rbacReleaseName(), - chartDir: rbacHelmChartPath, - parameters: this.rbacHelmParameters(), - }) - return super.upgradeChart() - } - - async removeChart() { - await removeGenericHelmChart(this.rbacReleaseName(), this.celoEnv) - return super.removeChart() - } - - async helmParameters() { - const kubeServiceAccountSecretNames = await this.rbacServiceAccountSecretNames() - return [ - ...(await super.helmParameters()), - `--set kube.serviceAccountSecretNames='{${kubeServiceAccountSecretNames.join(',')}}'`, - ] - } - - rbacHelmParameters() { - return [ - `--set environment.name=${this.celoEnv}`, - `--set environment.currencyPair=${this.currencyPair}`, - `--set oracle.replicas=${this.replicas}`, - ] - } - - async rbacServiceAccountSecretNames() { - return [...Array(this.replicas).keys()].map((i) => { - return `${this.rbacReleaseName()}-secret-${i}` - }) - } - - rbacReleaseName() { - return `${this.celoEnv}-${this.currencyPair.toLocaleLowerCase()}-oracle-rbac` - } -} diff --git a/packages/celotool/src/lib/kubernetes.ts b/packages/celotool/src/lib/kubernetes.ts deleted file mode 100644 index ce4f462b6..000000000 --- a/packages/celotool/src/lib/kubernetes.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { execCmd, execCmdWithExitOnFailure } from './cmd-utils' -import { envVar, fetchEnv } from './env-utils' - -export async function scaleResource( - namespace: string, - type: string, - resourceName: string, - replicaCount: number, - allowFail: boolean = false -) { - const execFn = allowFail ? execCmd : execCmdWithExitOnFailure - const run = () => - execFn( - `kubectl scale ${type} ${resourceName} --replicas=${replicaCount} --namespace ${namespace}` - ) - if (allowFail) { - try { - return run() - } catch (e) { - console.info('Error scaling resource, not failing', e) - return Promise.resolve() - } - } - return run() -} - -export async function getStatefulSetReplicas(namespace: string, resourceName: string) { - const [replicas] = await execCmd( - `kubectl get statefulset ${resourceName} --namespace ${namespace} -o jsonpath={.status.replicas}` - ) - return parseInt(replicas, 10) -} - -export async function getRandomTxNodeIP(namespace: string) { - const txNodes = parseInt(fetchEnv(envVar.TX_NODES), 10) - const randomNumber = Math.floor(Math.random() * txNodes) - const [address] = await execCmdWithExitOnFailure( - `kubectl get service/${namespace}-service-${randomNumber} --namespace ${namespace} -o jsonpath='{.status.loadBalancer.ingress[0].ip}'` - ) - return address -} - -export async function deleteResource( - namespace: string, - type: string, - resourceName: string, - allowFail: boolean = false -) { - const execFn = allowFail ? execCmd : execCmdWithExitOnFailure - const run = () => execFn(`kubectl delete ${type} ${resourceName} --namespace ${namespace}`) - if (allowFail) { - try { - // By awaiting here, we ensure that a rejected promise gets caught - return await run() - } catch (e) { - console.info('Error deleting resource, not failing', e) - return Promise.resolve() - } - } - return run() -} - -/** - * Returns a sorted array of used node ports - */ -export async function getAllUsedNodePorts( - namespace?: string, - cmdFlags?: { [key: string]: string } -) { - const namespaceFlag = namespace ? `--namespace ${namespace}` : `--all-namespaces` - const cmdFlagStrs = cmdFlags - ? Object.entries(cmdFlags).map(([flag, value]) => `--${flag} ${value}`) - : [] - const [output] = await execCmd( - `kubectl get svc ${namespaceFlag} ${cmdFlagStrs.join( - ' ' - )} -o go-template='{{range .items}}{{range .spec.ports}}{{if .nodePort}}{{.nodePort}}{{"\\n"}}{{end}}{{end}}{{end}}'` - ) - const nodePorts = output - .trim() - .split('\n') - .filter((portStr: string) => portStr.length) - .map((portStr: string) => parseInt(portStr, 10)) - // Remove duplicates and sort low -> high - return Array.from(new Set(nodePorts)).sort((a: number, b: number) => a - b) -} - -export async function getService(serviceName: string, namespace: string) { - try { - const [output] = await execCmd( - `kubectl get svc ${serviceName} --namespace ${namespace} -o json` - ) - return JSON.parse(output) - } catch (e) { - return undefined - } -} - -export async function getServerVersion() { - const [output] = await execCmd(`kubectl version -o json`) - const jsonOutput = JSON.parse(output) - const [minorNumberStr] = jsonOutput.serverVersion.minor.match(/^([0-9]+)/g) - if (!minorNumberStr) { - throw Error('Could not get minor version') - } - return { - major: parseInt(jsonOutput.serverVersion.major, 10), - minor: parseInt(minorNumberStr, 10), - } -} diff --git a/packages/celotool/src/lib/leaderboard.ts b/packages/celotool/src/lib/leaderboard.ts deleted file mode 100644 index 9ddab0316..000000000 --- a/packages/celotool/src/lib/leaderboard.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { execCmd } from 'src/lib/cmd-utils' -import { envVar, fetchEnv } from 'src/lib/env-utils' -import { - installGenericHelmChart, - removeGenericHelmChart, - upgradeGenericHelmChart, -} from 'src/lib/helm_deploy' -const yaml = require('js-yaml') -const helmChartPath = '../helm-charts/leaderboard' - -export async function installHelmChart(celoEnv: string) { - return installGenericHelmChart({ - namespace: celoEnv, - releaseName: releaseName(celoEnv), - chartDir: helmChartPath, - parameters: await helmParameters(celoEnv), - }) -} - -export async function removeHelmRelease(celoEnv: string) { - await removeGenericHelmChart(releaseName(celoEnv), celoEnv) -} - -export async function upgradeHelmChart(celoEnv: string) { - await upgradeGenericHelmChart({ - namespace: celoEnv, - releaseName: releaseName(celoEnv), - chartDir: helmChartPath, - parameters: await helmParameters(celoEnv), - }) -} - -export async function helmParameters(celoEnv: string) { - const dbValues = await getBlockscoutHelmValues(celoEnv) - return [ - `--set leaderboard.db.connection_name=${dbValues.connection_name}`, - `--set leaderboard.db.username=${dbValues.username}`, - `--set leaderboard.db.password=${dbValues.password}`, - `--set leaderboard.image.repository=${fetchEnv(envVar.LEADERBOARD_DOCKER_IMAGE_REPOSITORY)}`, - `--set leaderboard.image.tag=${fetchEnv(envVar.LEADERBOARD_DOCKER_IMAGE_TAG)}`, - `--set leaderboard.sheet=${fetchEnv(envVar.LEADERBOARD_SHEET)}`, - `--set leaderboard.token=${fetchEnv(envVar.LEADERBOARD_TOKEN)}`, - `--set leaderboard.credentials=${fetchEnv(envVar.LEADERBOARD_CREDENTIALS)}`, - `--set leaderboard.web3=https://${celoEnv}-forno.${fetchEnv(envVar.CLUSTER_DOMAIN_NAME)}.org`, - ] -} - -function releaseName(celoEnv: string) { - return `${celoEnv}-leaderboard` -} - -export async function getBlockscoutHelmValues(celoEnv: string) { - const [output] = await execCmd(`helm get values ${celoEnv}-blockscout`) - const blockscoutValues: any = yaml.safeLoad(output) - return blockscoutValues.blockscout.db -} diff --git a/packages/celotool/src/lib/load-test-logs-collector.ts b/packages/celotool/src/lib/load-test-logs-collector.ts deleted file mode 100644 index 2c89decdd..000000000 --- a/packages/celotool/src/lib/load-test-logs-collector.ts +++ /dev/null @@ -1,231 +0,0 @@ -import { - LOG_TAG_BLOCKSCOUT_TIME_MEASUREMENT, - LOG_TAG_BLOCKSCOUT_TIMEOUT, - LOG_TAG_BLOCKSCOUT_VALIDATION_ERROR, - LOG_TAG_GETH_RPC_ERROR, - LOG_TAG_TRANSACTION_ERROR, - LOG_TAG_TRANSACTION_VALIDATION_ERROR, - LOG_TAG_TX_TIME_MEASUREMENT, -} from 'src/lib/geth' - -export interface TimeStatsBase { - count: number - totalTime: number - maximalTime: number - minimalTime: number -} - -export interface TimeStatsAccumulated extends TimeStatsBase { - durations: number[] -} - -export interface BlockscoutStats extends TimeStatsAccumulated { - timeouts: number - validationErrors: any[] -} - -export interface ErrorsStatsBase { - count: number - errors: any[] -} - -export interface TransactionsErrorsState extends ErrorsStatsBase { - validationCount: number - validationErrors: any[] -} - -export interface LogsAggregator { - /* State storage */ - podsStats: any - blockscoutStats: BlockscoutStats - transactionsStats: { [key: string]: TimeStatsAccumulated } - transactionsErrors: { [key: string]: TransactionsErrorsState } - gethRPCErrors: any[] - - /* Public handler for mutating the state */ - handleNewEntry: (json: any) => void - - handleMultipleEntries: (messages: any[]) => void - - /* Returns summry in JSON */ - getSummary: () => string - - /* Helper functions */ - _initTransactionsStatsForToken: (token: string) => void - _initTransactionsErrorsForToken: (token: string) => void - _updateTimeStats: (json: any, statsStorage: TimeStatsAccumulated) => void - - /* State mutators depending on the event type */ - _handleTxTimeMeasurement: (json: any, token: string) => void - _handleTxError: (json: any, token: string) => void - _handleTxValidationError: (json: any, token: string) => void - _handleBlockscoutTimeout: () => void - _handleBlockscoutTimeMeasurement: (json: any) => void - _handleBlockscoutValidationError: (json: any) => void - _handleGethRPCError: (json: any) => void -} - -export const createLogsAggregator = () => { - const allowedTags = [ - LOG_TAG_TX_TIME_MEASUREMENT, - LOG_TAG_BLOCKSCOUT_TIME_MEASUREMENT, - LOG_TAG_TRANSACTION_ERROR, - LOG_TAG_TRANSACTION_VALIDATION_ERROR, - LOG_TAG_BLOCKSCOUT_TIMEOUT, - LOG_TAG_BLOCKSCOUT_VALIDATION_ERROR, - LOG_TAG_GETH_RPC_ERROR, - ] - - const logsAggregator: LogsAggregator = { - podsStats: {}, - blockscoutStats: { - count: 0, - totalTime: 0, - maximalTime: 0, - minimalTime: Number.MAX_SAFE_INTEGER, - timeouts: 0, - validationErrors: [], - durations: [], - }, - transactionsStats: {}, - transactionsErrors: {}, - gethRPCErrors: [], - - _initTransactionsStatsForToken(token: string) { - if (!this.transactionsStats[token]) { - this.transactionsStats[token] = { - count: 0, - totalTime: 0, - maximalTime: 0, - minimalTime: Number.MAX_SAFE_INTEGER, - durations: [], - } - } - }, - _initTransactionsErrorsForToken(token: string) { - if (!this.transactionsErrors[token]) { - this.transactionsErrors[token] = { - count: 0, - errors: [], - validationCount: 0, - validationErrors: [], - } - } - }, - _updateTimeStats(json: any, statsStorage: TimeStatsAccumulated) { - try { - const timeTaken = parseInt(json.p_time, 10) - statsStorage.count += 1 - statsStorage.totalTime += timeTaken - statsStorage.maximalTime = Math.max(statsStorage.maximalTime, timeTaken) - statsStorage.minimalTime = Math.min(statsStorage.minimalTime, timeTaken) - statsStorage.durations.push(timeTaken) - } catch (ignored) { - // ignore errors - } - }, - - _handleTxTimeMeasurement(json: any, token: string) { - this._initTransactionsStatsForToken(token) - this._updateTimeStats(json, this.transactionsStats[token]) - }, - _handleTxError(json: any, token: string) { - this._initTransactionsErrorsForToken(token) - if (json.error) { - this.transactionsErrors[token].count += 1 - this.transactionsErrors[token].errors.push(json.error) - } - }, - _handleTxValidationError(json: any, token: string) { - this._initTransactionsErrorsForToken(token) - if (json.error) { - this.transactionsErrors[token].validationCount += 1 - this.transactionsErrors[token].validationErrors.push(json.error) - } - }, - _handleBlockscoutTimeout() { - this.blockscoutStats.timeouts += 1 - }, - _handleBlockscoutTimeMeasurement(json: any) { - this._updateTimeStats(json, this.blockscoutStats) - }, - _handleBlockscoutValidationError(json: any) { - if (json.error) { - this.blockscoutStats.validationErrors.push(json.error) - } - }, - _handleGethRPCError(json: any) { - if (json.error) { - this.gethRPCErrors.push(json.error) - } - }, - - handleMultipleEntries(messages: any[]) { - messages.forEach((json) => { - this.handleNewEntry(json) - }) - }, - - handleNewEntry(json: any) { - if (allowedTags.indexOf(json.tag) < 0) { - return - } - - if (!this.podsStats[json.podID]) { - this.podsStats[json.podID] = 1 - } else { - this.podsStats[json.podID] += 1 - } - - const token = json.token - switch (json.tag) { - case LOG_TAG_TX_TIME_MEASUREMENT: - this._handleTxTimeMeasurement(json, token) - break - - case LOG_TAG_TRANSACTION_ERROR: - this._handleTxError(json, token) - break - - case LOG_TAG_TRANSACTION_VALIDATION_ERROR: - this._handleTxValidationError(json, token) - break - - case LOG_TAG_BLOCKSCOUT_TIME_MEASUREMENT: - this._handleBlockscoutTimeMeasurement(json) - break - - case LOG_TAG_BLOCKSCOUT_TIMEOUT: - this._handleBlockscoutTimeout() - break - - case LOG_TAG_BLOCKSCOUT_VALIDATION_ERROR: - this._handleBlockscoutValidationError(json) - break - - case LOG_TAG_GETH_RPC_ERROR: - this._handleGethRPCError(json) - break - - default: - break - } - }, - - getSummary() { - const collectedLogsSummary = { - podsStats: this.podsStats, - blockscoutStats: this.blockscoutStats, - transactionsStats: this.transactionsStats, - transactionsErrors: this.transactionsErrors, - gethRPCErrors: this.gethRPCErrors, - } - - const summaryJSON = JSON.stringify(collectedLogsSummary, null, 2) - - return summaryJSON - }, - } - - return logsAggregator -} diff --git a/packages/celotool/src/lib/load-test.ts b/packages/celotool/src/lib/load-test.ts deleted file mode 100644 index 052cb451b..000000000 --- a/packages/celotool/src/lib/load-test.ts +++ /dev/null @@ -1,128 +0,0 @@ -import sleep from 'sleep-promise' -import { LoadTestArgv } from 'src/cmds/deploy/initial/load-test' -import { getBlockscoutUrl } from 'src/lib/endpoints' -import { envVar, fetchEnv } from 'src/lib/env-utils' -import { getEnodesWithExternalIPAddresses } from 'src/lib/geth' -import { - installGenericHelmChart, - removeGenericHelmChart, - saveHelmValuesFile, - upgradeGenericHelmChart, -} from 'src/lib/helm_deploy' -import { scaleResource } from 'src/lib/kubernetes' - -const chartDir = '../helm-charts/load-test/' - -function releaseName(celoEnv: string) { - return `${celoEnv}-load-test` -} - -export async function installHelmChart( - celoEnv: string, - blockscoutProb: number, - delayMs: number, - replicas: number, - threads: number -) { - const params = await helmParameters(celoEnv, blockscoutProb, delayMs, replicas, threads) - return installGenericHelmChart({ - namespace: celoEnv, - releaseName: releaseName(celoEnv), - chartDir, - parameters: params, - }) -} - -export async function upgradeHelmChart( - celoEnv: string, - blockscoutProb: number, - delayMs: number, - replicas: number, - threads: number -) { - const params = await helmParameters(celoEnv, blockscoutProb, delayMs, replicas, threads) - await upgradeGenericHelmChart({ - namespace: celoEnv, - releaseName: releaseName(celoEnv), - chartDir, - parameters: params, - }) -} - -// scales down all pods, upgrades, then scales back up -export async function resetAndUpgrade( - celoEnv: string, - blockscoutProb: number, - delayMs: number, - replicas: number, - threads: number -) { - const loadTestStatefulSetName = `${celoEnv}-load-test` - - console.info('Scaling load-test StatefulSet down to 0...') - await scaleResource(celoEnv, 'StatefulSet', loadTestStatefulSetName, 0) - - await sleep(3000) - - await upgradeHelmChart(celoEnv, blockscoutProb, delayMs, replicas, threads) - - await sleep(3000) - - console.info(`Scaling load-test StatefulSet back up to ${replicas}...`) - await scaleResource(celoEnv, 'StatefulSet', loadTestStatefulSetName, replicas) -} - -export function setArgvDefaults(argv: LoadTestArgv) { - // Variables from the .env file are not set as environment variables - // by the time the builder is run, so we set the default here - if (argv.delay < 0) { - argv.delay = parseInt(fetchEnv(envVar.LOAD_TEST_TX_DELAY_MS), 10) - } - if (argv.replicas < 0) { - argv.replicas = parseInt(fetchEnv(envVar.LOAD_TEST_CLIENTS), 10) - } - if (argv.threads < 0) { - argv.replicas = parseInt(fetchEnv(envVar.LOAD_TEST_THREADS), 1) - } -} - -export async function removeHelmRelease(celoEnv: string) { - return removeGenericHelmChart(`${celoEnv}-load-test`, celoEnv) -} - -async function helmParameters( - celoEnv: string, - blockscoutProb: number, - delayMs: number, - replicas: number, - threads: number -) { - const enodes = await getEnodesWithExternalIPAddresses(celoEnv) - const staticNodesJsonB64 = Buffer.from(JSON.stringify(enodes)).toString('base64') - // Uses the genesis file from google storage to ensure it's the correct genesis for the network - const valueFilePath = `/tmp/${celoEnv}-testnet-values.yaml` - await saveHelmValuesFile(celoEnv, valueFilePath, true, true) - - return [ - `-f ${valueFilePath}`, - `--set geth.accountSecret="${fetchEnv(envVar.GETH_ACCOUNT_SECRET)}"`, - `--set blockscout.measurePercent=${blockscoutProb}`, - `--set blockscout.url=${getBlockscoutUrl(celoEnv)}`, - `--set celotool.image.repository=${fetchEnv(envVar.CELOTOOL_DOCKER_IMAGE_REPOSITORY)}`, - `--set celotool.image.tag=${fetchEnv(envVar.CELOTOOL_DOCKER_IMAGE_TAG)}`, - `--set delay=${delayMs}`, // send txs every 5 seconds - `--set environment=${celoEnv}`, - `--set geth.image.repository=${fetchEnv(envVar.GETH_NODE_DOCKER_IMAGE_REPOSITORY)}`, - `--set geth.image.tag=${fetchEnv(envVar.GETH_NODE_DOCKER_IMAGE_TAG)}`, - `--set geth.networkID=${fetchEnv(envVar.NETWORK_ID)}`, - `--set geth.staticNodes="${staticNodesJsonB64}"`, - `--set geth.verbosity=${fetchEnv('GETH_VERBOSITY')}`, - `--set mnemonic="${fetchEnv(envVar.MNEMONIC)}"`, - `--set replicas=${replicas}`, - `--set threads=${threads}`, - `--set genesis.useGenesisFileBase64=false`, - `--set genesis.network=${celoEnv}`, - `--set use_random_recipient=${fetchEnv(envVar.LOAD_TEST_USE_RANDOM_RECIPIENT)}`, - `--set reuse_light_clients=true`, - ] -} diff --git a/packages/celotool/src/lib/migration-utils.ts b/packages/celotool/src/lib/migration-utils.ts deleted file mode 100644 index ae841e269..000000000 --- a/packages/celotool/src/lib/migration-utils.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { generateKeys } from '@celo/cryptographic-utils/lib/account' -import { envVar, fetchEnv, fetchEnvOrFallback } from './env-utils' -import { - AccountType, - generatePrivateKey, - getAddressesFor, - getFaucetedAccounts, - getPrivateKeysFor, - privateKeyToAddress, -} from './generate_utils' -import { ensure0x } from './utils' - -const DEFAULT_FAUCET_CUSD_WEI = '60000000000000000000000' /* 60k Celo Dollars */ - -export async function getKey(mnemonic: string, account: TestAccounts) { - const key = await generateKeys(mnemonic, undefined, 0, account) - return { ...key, address: privateKeyToAddress(key.privateKey) } -} - -// From env-tests package -export enum TestAccounts { - Root, - TransferFrom, - TransferTo, - Exchange, - Oracle, - GovernanceApprover, - ReserveSpender, - ReserveCustodian, -} - -export function minerForEnv() { - return privateKeyToAddress( - generatePrivateKey(fetchEnv(envVar.MNEMONIC), AccountType.VALIDATOR, 0) - ) -} - -export function validatorKeys() { - return getPrivateKeysFor( - AccountType.VALIDATOR, - fetchEnv(envVar.MNEMONIC), - parseInt(fetchEnv(envVar.VALIDATORS), 10) - ).map(ensure0x) -} - -function getAttestationKeys() { - return getPrivateKeysFor( - AccountType.ATTESTATION, - fetchEnv(envVar.MNEMONIC), - parseInt(fetchEnv(envVar.VALIDATORS), 10) - ).map(ensure0x) -} - -export async function migrationOverrides(faucet: boolean) { - let overrides = {} - if (faucet) { - const mnemonic = fetchEnv(envVar.MNEMONIC) - const faucetedAccountAddresses = getFaucetedAccounts(mnemonic).map((account) => account.address) - const attestationBotAddresses = getAddressesFor(AccountType.ATTESTATION_BOT, mnemonic, 10) - const validatorAddresses = getAddressesFor(AccountType.VALIDATOR, mnemonic, 1) - const envTestRoot = await getKey(mnemonic, TestAccounts.Root) - const envTestReserveCustodian = await getKey(mnemonic, TestAccounts.ReserveCustodian) - const envTestOracle = await getKey(mnemonic, TestAccounts.Oracle) - const envTestGovernanceApprover = await getKey(mnemonic, TestAccounts.GovernanceApprover) - const envTestReserveSpender = await getKey(mnemonic, TestAccounts.ReserveSpender) - const initialAddresses = [ - ...faucetedAccountAddresses, - ...attestationBotAddresses, - ...validatorAddresses, - envTestRoot.address, - envTestOracle.address, - ] - - const initialBalance = fetchEnvOrFallback(envVar.FAUCET_CUSD_WEI, DEFAULT_FAUCET_CUSD_WEI) - - overrides = { - ...overrides, - stableToken: { - initialBalances: { - addresses: initialAddresses, - values: initialAddresses.map(() => initialBalance), - }, - oracles: [ - ...getAddressesFor(AccountType.PRICE_ORACLE, mnemonic, 1), - minerForEnv(), - envTestOracle.address, - ], - }, - // from migrationsConfig - governanceApproverMultiSig: { - signatories: [minerForEnv(), envTestGovernanceApprover.address], - numRequiredConfirmations: 1, - numInternalRequiredConfirmations: 1, - }, - // from migrationsConfig: - reserve: { - initialBalance: 100000000, // CELO - frozenAssetsStartBalance: 80000000, // Matches Mainnet after CGP-6 - frozenAssetsDays: 182, // 3x Mainnet thawing rate - otherAddresses: [envTestReserveCustodian.address], - }, - // from migrationsConfig - reserveSpenderMultiSig: { - signatories: [minerForEnv(), envTestReserveSpender.address], - numRequiredConfirmations: 1, - numInternalRequiredConfirmations: 1, - }, - } - } - - return { - ...overrides, - validators: { - validatorKeys: validatorKeys(), - attestationKeys: getAttestationKeys(), - }, - } -} - -export function truffleOverrides() { - return { - from: minerForEnv(), - } -} diff --git a/packages/celotool/src/lib/mock-oracle.ts b/packages/celotool/src/lib/mock-oracle.ts deleted file mode 100644 index 778bb206c..000000000 --- a/packages/celotool/src/lib/mock-oracle.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { envVar, fetchEnv } from 'src/lib/env-utils' -import { getPrivateTxNodeClusterIP } from 'src/lib/geth' -import { installGenericHelmChart, removeGenericHelmChart } from 'src/lib/helm_deploy' - -const helmChartPath = '../helm-charts/mock-oracle' - -export async function installHelmChart(celoEnv: string) { - return installGenericHelmChart({ - namespace: celoEnv, - releaseName: releaseName(celoEnv), - chartDir: helmChartPath, - parameters: await helmParameters(celoEnv), - }) -} -export async function removeHelmRelease(celoEnv: string) { - await removeGenericHelmChart(releaseName(celoEnv), celoEnv) -} - -async function helmParameters(celoEnv: string) { - const nodeIp = await getPrivateTxNodeClusterIP(celoEnv) - const nodeUrl = `http://${nodeIp}:8545` - return [ - `--set celotool.image.repository=${fetchEnv(envVar.CELOTOOL_DOCKER_IMAGE_REPOSITORY)}`, - `--set celotool.image.tag=${fetchEnv(envVar.CELOTOOL_DOCKER_IMAGE_TAG)}`, - `--set mnemonic="${fetchEnv(envVar.MNEMONIC)}"`, - `--set oracle.cronSchedule="${fetchEnv(envVar.MOCK_ORACLE_CRON_SCHEDULE)}"`, - `--set oracle.image.repository=${fetchEnv(envVar.MOCK_ORACLE_DOCKER_IMAGE_REPOSITORY)}`, - `--set oracle.image.tag=${fetchEnv(envVar.MOCK_ORACLE_DOCKER_IMAGE_TAG)}`, - `--set celocli.nodeUrl=${nodeUrl}`, - `--set celocli.image.repository=${fetchEnv(envVar.CELOCLI_STANDALONE_IMAGE_REPOSITORY)}`, - `--set celocli.image.tag=${fetchEnv(envVar.CELOCLI_STANDALONE_IMAGE_TAG)}`, - ] -} - -function releaseName(celoEnv: string) { - return `${celoEnv}-mock-oracle` -} diff --git a/packages/celotool/src/lib/odis.ts b/packages/celotool/src/lib/odis.ts deleted file mode 100644 index 8a27e7047..000000000 --- a/packages/celotool/src/lib/odis.ts +++ /dev/null @@ -1,201 +0,0 @@ -import { DynamicEnvVar, envVar, fetchEnv } from 'src/lib/env-utils' -import { - installGenericHelmChart, - removeGenericHelmChart, - upgradeGenericHelmChart, -} from 'src/lib/helm_deploy' -import { - createKeyVaultIdentityIfNotExists, - deleteAzureKeyVaultIdentity, - getAzureKeyVaultIdentityName, -} from './azure' -import { getAksClusterConfig, getContextDynamicEnvVarValues } from './context-utils' - -const helmChartPath = '../helm-charts/odis' - -/** - * Information for the Azure Key Vault - */ -interface ODISSignerKeyVaultConfig { - vaultName: string - pnpKeyNameBase: string - pnpKeyLatestVersion: string - domainsKeyNameBase: string - domainsKeyLatestVersion: string -} - -/** - * Information for the ODIS postgres db - */ -interface ODISSignerDatabaseConfig { - host: string - port: string - username: string - password: string -} - -/** - * Information for the Blockchain provider connection - */ -interface ODISSignerBlockchainConfig { - blockchainApiKey: string -} - -/** - * Information for the ODIS logging - */ -interface ODISSignerLoggingConfig { - level: string - format: string -} - -/* - * Prefix for the cluster's identity name - */ -const identityNamePrefix = 'ODISSIGNERID' - -/** - * Env vars corresponding to each value for the ODISSignerKeyVaultConfig for a particular context - */ -const contextODISSignerKeyVaultConfigDynamicEnvVars: { - [k in keyof ODISSignerKeyVaultConfig]: DynamicEnvVar -} = { - vaultName: DynamicEnvVar.ODIS_SIGNER_AZURE_KEYVAULT_NAME, - pnpKeyNameBase: DynamicEnvVar.ODIS_SIGNER_AZURE_KEYVAULT_PNP_KEY_NAME_BASE, - pnpKeyLatestVersion: DynamicEnvVar.ODIS_SIGNER_AZURE_KEYVAULT_PNP_KEY_LATEST_VERSION, - domainsKeyNameBase: DynamicEnvVar.ODIS_SIGNER_AZURE_KEYVAULT_DOMAINS_KEY_NAME_BASE, - domainsKeyLatestVersion: DynamicEnvVar.ODIS_SIGNER_AZURE_KEYVAULT_DOMAINS_KEY_LATEST_VERSION, -} - -/** - * Env vars corresponding to each value for the ODISSignerDatabaseConfig for a particular context - */ -const contextDatabaseConfigDynamicEnvVars: { - [k in keyof ODISSignerDatabaseConfig]: DynamicEnvVar -} = { - host: DynamicEnvVar.ODIS_SIGNER_DB_HOST, - port: DynamicEnvVar.ODIS_SIGNER_DB_PORT, - username: DynamicEnvVar.ODIS_SIGNER_DB_USERNAME, - password: DynamicEnvVar.ODIS_SIGNER_DB_PASSWORD, -} - -/** - * Env vars corresponding to each value for the ODISSignerBlockchainConfig for a particular context - */ -const contextBlockchainConfigDynamicEnvVars: { - [k in keyof ODISSignerBlockchainConfig]: DynamicEnvVar -} = { - blockchainApiKey: DynamicEnvVar.ODIS_SIGNER_BLOCKCHAIN_API_KEY, -} - -/** - * Env vars corresponding to each value for the logging for a particular context - */ -const contextLoggingConfigDynamicEnvVars: { - [k in keyof ODISSignerLoggingConfig]: DynamicEnvVar -} = { - level: DynamicEnvVar.ODIS_SIGNER_LOG_LEVEL, - format: DynamicEnvVar.ODIS_SIGNER_LOG_FORMAT, -} - -function releaseName(celoEnv: string, context: string) { - const contextK8sFriendly = context.toLowerCase().replace(/_/g, '-') - return `${celoEnv}--${contextK8sFriendly}--odissigner` -} - -export async function installODISHelmChart(celoEnv: string, context: string) { - return installGenericHelmChart({ - namespace: celoEnv, - releaseName: releaseName(celoEnv, context), - chartDir: helmChartPath, - parameters: await helmParameters(celoEnv, context), - }) -} - -export async function upgradeODISChart(celoEnv: string, context: string) { - return upgradeGenericHelmChart({ - namespace: celoEnv, - releaseName: releaseName(celoEnv, context), - chartDir: helmChartPath, - parameters: await helmParameters(celoEnv, context), - }) -} - -export async function removeHelmRelease(celoEnv: string, context: string) { - await removeGenericHelmChart(releaseName(celoEnv, context), celoEnv) - const keyVaultConfig = getContextDynamicEnvVarValues( - contextODISSignerKeyVaultConfigDynamicEnvVars, - context - ) - - await deleteAzureKeyVaultIdentity( - context, - getAzureKeyVaultIdentityName(context, identityNamePrefix, keyVaultConfig.vaultName), - keyVaultConfig.vaultName - ) -} - -async function helmParameters(celoEnv: string, context: string) { - const blockchainConfig = getContextDynamicEnvVarValues( - contextBlockchainConfigDynamicEnvVars, - context - ) - const databaseConfig = getContextDynamicEnvVarValues(contextDatabaseConfigDynamicEnvVars, context) - const keyVaultConfig = getContextDynamicEnvVarValues( - contextODISSignerKeyVaultConfigDynamicEnvVars, - context - ) - - const loggingConfig = getContextDynamicEnvVarValues(contextLoggingConfigDynamicEnvVars, context, { - level: 'trace', - format: 'stackdriver', - }) - - const clusterConfig = getAksClusterConfig(context) - - return [ - `--set environment.name=${celoEnv}`, - `--set environment.cluster.name=${clusterConfig.clusterName}`, - `--set environment.cluster.location=${clusterConfig.regionName}`, - `--set image.repository=${fetchEnv(envVar.ODIS_SIGNER_DOCKER_IMAGE_REPOSITORY)}`, - `--set image.tag=${fetchEnv(envVar.ODIS_SIGNER_DOCKER_IMAGE_TAG)}`, - `--set db.host=${databaseConfig.host}`, - `--set db.port=${databaseConfig.port}`, - `--set db.username=${databaseConfig.username}`, - `--set db.password='${databaseConfig.password}'`, - `--set keystore.vaultName=${keyVaultConfig.vaultName}`, - `--set keystore.pnpKeyNameBase=${keyVaultConfig.pnpKeyNameBase}`, - `--set keystore.domainsKeyNameBase=${keyVaultConfig.domainsKeyNameBase}`, - `--set keystore.pnpKeyLatestVersion=${keyVaultConfig.pnpKeyLatestVersion}`, - `--set keystore.domainsKeyLatestVersion=${keyVaultConfig.domainsKeyLatestVersion}`, - `--set api.pnpAPIEnabled=${fetchEnv(envVar.ODIS_SIGNER_PNP_API_ENABLED)}`, - `--set api.domainsAPIEnabled=${fetchEnv(envVar.ODIS_SIGNER_DOMAINS_API_ENABLED)}`, - `--set blockchainProvider=${fetchEnv(envVar.ODIS_SIGNER_BLOCKCHAIN_PROVIDER)}`, - `--set blockchainApiKey=${blockchainConfig.blockchainApiKey}`, - `--set log.level=${loggingConfig.level}`, - `--set log.format=${loggingConfig.format}`, - ].concat(await ODISSignerKeyVaultIdentityHelmParameters(context, keyVaultConfig)) -} - -/** - * Returns an array of helm command line parameters for the ODIS Signer key vault identity. - */ -async function ODISSignerKeyVaultIdentityHelmParameters( - context: string, - keyVaultConfig: ODISSignerKeyVaultConfig -) { - const azureKVIdentity = await createKeyVaultIdentityIfNotExists( - context, - getAzureKeyVaultIdentityName(context, identityNamePrefix, keyVaultConfig.vaultName), - keyVaultConfig.vaultName, - null, - null, - ['get'] - ) - const params: string[] = [ - `--set azureKVIdentity.id=${azureKVIdentity.id}`, - `--set azureKVIdentity.clientId=${azureKVIdentity.clientId}`, - ] - - return params -} diff --git a/packages/celotool/src/lib/oracle.ts b/packages/celotool/src/lib/oracle.ts deleted file mode 100644 index 1b8d20e9a..000000000 --- a/packages/celotool/src/lib/oracle.ts +++ /dev/null @@ -1,251 +0,0 @@ -import { ensureLeading0x } from '@celo/utils/src/address' -import { DynamicEnvVar, envVar, fetchEnv } from 'src/lib/env-utils' -import yargs from 'yargs' -import { getCloudProviderFromContext, getDynamicEnvVarValues } from './context-utils' -import { getOraclePrivateKeysFor, privateKeyToAddress } from './generate_utils' -import { AksClusterConfig } from './k8s-cluster/aks' -import { BaseClusterManager, CloudProvider } from './k8s-cluster/base' -import { - AksHsmOracleDeployer, - AksHsmOracleDeploymentConfig, - AksHsmOracleIdentity, -} from './k8s-oracle/aks-hsm' -import { BaseOracleDeployer, CurrencyPair } from './k8s-oracle/base' -import { - PrivateKeyOracleDeployer, - PrivateKeyOracleDeploymentConfig, - PrivateKeyOracleIdentity, -} from './k8s-oracle/pkey' - -/** - * Maps each cloud provider to the correct function to get the appropriate - * HSM-based oracle deployer. - */ -const hsmOracleDeployerGetterByCloudProvider: { - [key in CloudProvider]?: ( - celoEnv: string, - context: string, - currencyPair: CurrencyPair, - useForno: boolean, - clusterManager: BaseClusterManager - ) => BaseOracleDeployer -} = { - [CloudProvider.AZURE]: getAksHsmOracleDeployer, -} - -/** - * Gets the appropriate oracle deployer for the given context. If the env vars - * specify that the oracle addresses should be generated from the mnemonic, - * then the cloud-provider agnostic deployer PrivateKeyOracleDeployer is used. - */ -export function getOracleDeployerForContext( - celoEnv: string, - context: string, - currencyPair: CurrencyPair, - useForno: boolean, - clusterManager: BaseClusterManager -) { - // If the mnemonic-based oracle address env var has a value, we should be using - // the private key oracle deployer - const { addressesFromMnemonicCount } = getDynamicEnvVarValues( - mnemonicBasedOracleIdentityConfigDynamicEnvVars, - { context, currencyPair }, - { - addressesFromMnemonicCount: '', - } - ) - - if (addressesFromMnemonicCount) { - const addressesFromMnemonicCountNum = parseInt(addressesFromMnemonicCount, 10) - // This is a cloud-provider agnostic deployer because it doesn't rely - // on cloud-specific HSMs - return getPrivateKeyOracleDeployer( - celoEnv, - context, - currencyPair, - useForno, - addressesFromMnemonicCountNum - ) - } - // If we've gotten this far, we should be using an HSM-based oracle deployer - const cloudProvider: CloudProvider = getCloudProviderFromContext(context) - const getDeployer = hsmOracleDeployerGetterByCloudProvider[cloudProvider] - if (getDeployer === undefined) { - throw new Error( - `Deployer not defined for CloudProvider: ${cloudProvider}. ` + - `Expecting one of: ${Object.keys(hsmOracleDeployerGetterByCloudProvider)}` - ) - } - return getDeployer(celoEnv, context, currencyPair, useForno, clusterManager) -} - -/** - * ----------- AksHsmOracleDeployer helpers ----------- - */ - -/** - * Gets an AksHsmOracleDeployer by looking at env var values - */ -function getAksHsmOracleDeployer( - celoEnv: string, - context: string, - currencyPair: CurrencyPair, - useForno: boolean, - clusterManager: BaseClusterManager -) { - const { addressKeyVaults } = getDynamicEnvVarValues( - aksHsmOracleIdentityConfigDynamicEnvVars, - { context, currencyPair }, - { - addressKeyVaults: '', - } - ) - const aksClusterConfig = clusterManager.clusterConfig as AksClusterConfig - const identities = getAksHsmOracleIdentities( - addressKeyVaults, - aksClusterConfig.resourceGroup, - currencyPair - ) - const deploymentConfig: AksHsmOracleDeploymentConfig = { - context, - clusterConfig: aksClusterConfig, - currencyPair, - identities, - useForno, - } - return new AksHsmOracleDeployer(deploymentConfig, celoEnv) -} - -/** - * Given a string addressAzureKeyVaults containing comma separated info of the form: - *
:: - * eg: 0x0000000000000000000000000000000000000000:keyVault0,0x0000000000000000000000000000000000000001:keyVault1:resourceGroup1 - * returns an array of AksHsmOracleIdentity in the same order - */ -export function getAksHsmOracleIdentities( - addressAzureKeyVaults: string, - defaultResourceGroup: string, - currencyPair: CurrencyPair -): AksHsmOracleIdentity[] { - const identityStrings = addressAzureKeyVaults.split(',') - const identities = [] - for (const identityStr of identityStrings) { - const [address, keyVaultName, resourceGroup] = identityStr.split(':') - // resourceGroup can be undefined - if (!address || !keyVaultName) { - throw Error( - `Address or key vault name is invalid. Address: ${address} Key Vault Name: ${keyVaultName}` - ) - } - identities.push({ - address, - currencyPair, - keyVaultName, - resourceGroup: resourceGroup || defaultResourceGroup, - }) - } - return identities -} - -/** - * Config values pulled from env vars used for generating an AksHsmOracleIdentity - */ -interface AksHsmOracleIdentityConfig { - addressKeyVaults: string -} - -/** - * Env vars corresponding to each value for the AksHsmOracleIdentityConfig for a particular context - */ -const aksHsmOracleIdentityConfigDynamicEnvVars: { - [k in keyof AksHsmOracleIdentityConfig]: DynamicEnvVar -} = { - addressKeyVaults: DynamicEnvVar.ORACLE_ADDRESS_AZURE_KEY_VAULTS, -} - -/** - * ----------- PrivateKeyOracleDeployer helpers ----------- - */ - -/** - * Gets an PrivateKeyOracleDeployer by looking at env var values and generating private keys - * from the mnemonic - */ -function getPrivateKeyOracleDeployer( - celoEnv: string, - context: string, - currencyPair: CurrencyPair, - useForno: boolean, - count: number -): PrivateKeyOracleDeployer { - const identities: PrivateKeyOracleIdentity[] = getOraclePrivateKeysFor( - currencyPair, - fetchEnv(envVar.MNEMONIC), - count - ).map((pkey) => ({ - address: privateKeyToAddress(pkey), - currencyPair, - privateKey: ensureLeading0x(pkey), - })) - const deploymentConfig: PrivateKeyOracleDeploymentConfig = { - context, - currencyPair, - identities, - useForno, - } - return new PrivateKeyOracleDeployer(deploymentConfig, celoEnv) -} - -/** - * Config values pulled from env vars used for generating a PrivateKeyOracleIdentity - * from a mnemonic - */ -interface MnemonicBasedOracleIdentityConfig { - addressesFromMnemonicCount: string -} - -/** - * Env vars corresponding to each value for the MnemonicBasedOracleIdentityConfig for a particular context - */ -const mnemonicBasedOracleIdentityConfigDynamicEnvVars: { - [k in keyof MnemonicBasedOracleIdentityConfig]: DynamicEnvVar -} = { - addressesFromMnemonicCount: DynamicEnvVar.ORACLE_ADDRESSES_FROM_MNEMONIC_COUNT, -} - -/** - * Add currencyPair to command arguments - * @param argv the yargs arguments list to add to - */ -export function addCurrencyPairMiddleware(argv: yargs.Argv) { - return argv.option('currencyPair', { - choices: [ - 'CELOUSD', - 'CELOEUR', - 'CELOBRL', - 'USDCUSD', - 'USDCEUR', - 'USDCBRL', - 'CELOXOF', - 'XOFEUR', - 'EUROCEUR', - 'EURXOF', - 'EUROCXOF', - ], - description: 'Oracle deployment to target based on currency pair', - demandOption: true, - type: 'string', - }) -} - -/** - * Add useForno to command arguments - * @param argv the yargs arguments list to add to - */ -export function addUseFornoMiddleware(argv: yargs.Argv) { - return argv.option('useForno', { - description: 'Uses forno for RPCs from the oracle clients', - default: false, - type: 'boolean', - }) -} diff --git a/packages/celotool/src/lib/port_forward.ts b/packages/celotool/src/lib/port_forward.ts deleted file mode 100644 index 297a326fa..000000000 --- a/packages/celotool/src/lib/port_forward.ts +++ /dev/null @@ -1,97 +0,0 @@ -/* tslint:disable: no-console */ -import { ChildProcess, spawnSync } from 'child_process' -import { execBackgroundCmd, execCmd } from './cmd-utils' - -function sleep(ms: number) { - return new Promise((resolve) => setTimeout(resolve, ms)) -} - -export const defaultPortsString = '8545:8545 8546:8546 9200:9200' - -const PORT_CONTROL_CMD = 'nc -z 127.0.0.1 8545' -const DEFAULT_COMPONENT = 'validators' - -async function getPortForwardCmd(celoEnv: string, component?: string, ports = defaultPortsString) { - return getKubernetesPortForwardCmd(celoEnv, component, ports) -} - -async function getKubernetesPortForwardCmd( - celoEnv: string, - component?: string, - ports = defaultPortsString -) { - if (!component) { - component = DEFAULT_COMPONENT - } - console.log(`Port-forwarding to ${celoEnv} ${component} ${ports}`) - const portForwardArgs = await getPortForwardArgs(celoEnv, component, ports) - return `kubectl ${portForwardArgs.join(' ')}` -} - -async function getPortForwardArgs(celoEnv: string, component?: string, ports = defaultPortsString) { - if (!component) { - component = DEFAULT_COMPONENT - } - console.log(`Port-forwarding to ${celoEnv} ${component} ${ports}`) - // The testnet helm chart used to have the label app=ethereum, but this was changed - // to app=testnet. To preserve backward compatibility, we search for both labels. - // It's not expected to ever have a situation where a namespace has pods with - // both labels. - const podName = await execCmd( - `kubectl get pods --namespace ${celoEnv} -l "app in (ethereum,testnet), component=${component}, release=${celoEnv}" --field-selector=status.phase=Running -o jsonpath="{.items[0].metadata.name}"` - ) - return ['port-forward', `--namespace=${celoEnv}`, podName[0], ...ports.split(' ')] -} - -export async function portForward(celoEnv: string, component?: string, ports?: string) { - try { - const portForwardCmd = await getPortForwardCmd(celoEnv, component, ports) - const splitCmd = portForwardCmd.split(' ') - console.log(`Port-forwarding to celoEnv ${celoEnv} ports ${ports}`) - console.log(`\t$ ${portForwardCmd}`) - await spawnSync(splitCmd[0], splitCmd.slice(1), { - stdio: 'inherit', - }) - } catch (error) { - console.error(`Unable to port-forward to ${celoEnv}`) - console.error(error) - process.exit(1) - } -} - -export async function portForwardAnd( - celoEnv: string, - cb: () => void, - component?: string, - ports?: string -) { - let childProcess: ChildProcess - - try { - childProcess = execBackgroundCmd(await getPortForwardCmd(celoEnv, component, ports)) - } catch (error) { - console.error(error) - process.exit(1) - throw new Error() // unreachable, but to fix typescript - } - - try { - let isConnected = false - while (!isConnected) { - if (process.env.CELOTOOL_VERBOSE === 'true') { - console.debug('Port Forward not ready yet...') - } - isConnected = await execCmd(PORT_CONTROL_CMD) - .then(() => true) - .catch(() => false) - await sleep(2000) - } - await cb() - childProcess.kill('SIGINT') - } catch (error) { - childProcess.kill('SIGINT') - - console.error(error) - process.exit(1) - } -} diff --git a/packages/celotool/src/lib/prometheus.ts b/packages/celotool/src/lib/prometheus.ts deleted file mode 100644 index 704b6caa2..000000000 --- a/packages/celotool/src/lib/prometheus.ts +++ /dev/null @@ -1,394 +0,0 @@ -import fs from 'fs' -import { createNamespaceIfNotExists } from './cluster' -import { execCmd, execCmdWithExitOnFailure } from './cmd-utils' -import { - DynamicEnvVar, - envVar, - fetchEnv, - fetchEnvOrFallback, - getDynamicEnvVarValue, -} from './env-utils' -import { - helmAddRepoAndUpdate, - installGenericHelmChart, - removeGenericHelmChart, - setHelmArray, - upgradeGenericHelmChart, -} from './helm_deploy' -import { BaseClusterConfig, CloudProvider } from './k8s-cluster/base' -import { - createServiceAccountIfNotExists, - getServiceAccountEmail, - getServiceAccountKey, - setupGKEWorkloadIdentities, -} from './service-account-utils' -import { outputIncludes, switchToGCPProject } from './utils' -const yaml = require('js-yaml') - -const helmChartPath = '../helm-charts/prometheus-stackdriver' -const releaseName = 'prometheus-stackdriver' -const kubeNamespace = 'prometheus' -const kubeServiceAccountName = releaseName -// stackdriver-prometheus-sidecar relevant links: -// GitHub: https://github.com/Stackdriver/stackdriver-prometheus-sidecar -// Container registry with latest tags: https://console.cloud.google.com/gcr/images/stackdriver-prometheus/GLOBAL/stackdriver-prometheus-sidecar?gcrImageListsize=30 -const sidecarImageTag = '0.8.2' -// Prometheus container registry with latest tags: https://hub.docker.com/r/prom/prometheus/tags -const prometheusImageTag = 'v2.38.0' - -const grafanaHelmRepo = 'grafana/grafana' -const grafanaChartVersion = '6.32.3' -const grafanaReleaseName = 'grafana' - -export async function installPrometheusIfNotExists( - context?: string, - clusterConfig?: BaseClusterConfig -) { - const prometheusExists = await outputIncludes( - `helm list -n prometheus`, - releaseName, - `prometheus-stackdriver exists, skipping install` - ) - if (!prometheusExists) { - console.info('Installing prometheus-stackdriver') - await installPrometheus(context, clusterConfig) - } -} - -async function installPrometheus(context?: string, clusterConfig?: BaseClusterConfig) { - await createNamespaceIfNotExists(kubeNamespace) - return installGenericHelmChart({ - namespace: kubeNamespace, - releaseName, - chartDir: helmChartPath, - parameters: await helmParameters(context, clusterConfig), - }) -} - -export async function removePrometheus() { - await removeGenericHelmChart(releaseName, kubeNamespace) -} - -export async function upgradePrometheus(context?: string, clusterConfig?: BaseClusterConfig) { - await createNamespaceIfNotExists(kubeNamespace) - return upgradeGenericHelmChart({ - namespace: kubeNamespace, - releaseName, - chartDir: helmChartPath, - parameters: await helmParameters(context, clusterConfig), - }) -} - -function getK8sContextVars( - clusterConfig?: BaseClusterConfig, - context?: string -): [string, string, string, string, string, boolean] { - const cloudProvider = clusterConfig ? getCloudProviderPrefix(clusterConfig!) : 'gcp' - const usingGCP = !clusterConfig || clusterConfig.cloudProvider === CloudProvider.GCP - let clusterName = usingGCP ? fetchEnv(envVar.KUBERNETES_CLUSTER_NAME) : clusterConfig!.clusterName - let gcloudProject, gcloudRegion, stackdriverDisabled - - if (context) { - gcloudProject = getDynamicEnvVarValue( - DynamicEnvVar.PROM_SIDECAR_GCP_PROJECT, - { context }, - fetchEnv(envVar.TESTNET_PROJECT_NAME) - ) - gcloudRegion = getDynamicEnvVarValue( - DynamicEnvVar.PROM_SIDECAR_GCP_REGION, - { context }, - fetchEnv(envVar.KUBERNETES_CLUSTER_ZONE) - ) - clusterName = getDynamicEnvVarValue( - DynamicEnvVar.KUBERNETES_CLUSTER_NAME, - { context }, - clusterName - ) - stackdriverDisabled = getDynamicEnvVarValue( - DynamicEnvVar.PROM_SIDECAR_DISABLED, - { context }, - clusterName - ) - } else { - gcloudProject = fetchEnv(envVar.TESTNET_PROJECT_NAME) - gcloudRegion = fetchEnv(envVar.KUBERNETES_CLUSTER_ZONE) - stackdriverDisabled = fetchEnvOrFallback(envVar.PROMETHEUS_DISABLE_STACKDRIVER_SIDECAR, 'false') - } - - return [cloudProvider, clusterName, gcloudProject, gcloudRegion, stackdriverDisabled, usingGCP] -} - -function getRemoteWriteParameters(context?: string): string[] { - const remoteWriteUrl = getDynamicEnvVarValue( - DynamicEnvVar.PROM_REMOTE_WRITE_URL, - { context }, - fetchEnv(envVar.PROMETHEUS_REMOTE_WRITE_URL) - ) - const remoteWriteUser = getDynamicEnvVarValue( - DynamicEnvVar.PROM_REMOTE_WRITE_USERNAME, - { context }, - fetchEnv(envVar.PROMETHEUS_REMOTE_WRITE_USERNAME) - ) - const remoteWritePassword = getDynamicEnvVarValue( - DynamicEnvVar.PROM_REMOTE_WRITE_PASSWORD, - { context }, - fetchEnv(envVar.PROMETHEUS_REMOTE_WRITE_PASSWORD) - ) - return [ - `--set remote_write.url='${remoteWriteUrl}'`, - `--set remote_write.basic_auth.username='${remoteWriteUser}'`, - `--set remote_write.basic_auth.password='${remoteWritePassword}'`, - ] -} - -async function helmParameters(context?: string, clusterConfig?: BaseClusterConfig) { - const [cloudProvider, clusterName, gcloudProject, gcloudRegion, stackdriverDisabled, usingGCP] = - getK8sContextVars(clusterConfig, context) - - const params = [ - `--set namespace=${kubeNamespace}`, - `--set gcloud.project=${gcloudProject}`, - `--set gcloud.region=${gcloudRegion}`, - `--set prometheus.imageTag=${prometheusImageTag}`, - `--set serviceAccount.name=${kubeServiceAccountName}`, - `--set cluster=${clusterName}`, - ] - - // Remote write to Grafana Cloud - if (fetchEnvOrFallback(envVar.PROMETHEUS_REMOTE_WRITE_URL, '') !== '') { - params.push(...getRemoteWriteParameters(context)) - } - - if (usingGCP) { - // Note: ssd is not the default storageClass in GCP clusters - params.push(`--set storageClassName=ssd`) - } else if (context?.startsWith('AZURE_ODIS')) { - params.push(`--set storageClassName=default`) - } - - if (stackdriverDisabled.toLowerCase() === 'false') { - params.push( - // Disable stackdriver sidecar env wide. TODO: Update to a contexted variable if needed - `--set stackdriver.disabled=false`, - `--set stackdriver.sidecar.imageTag=${sidecarImageTag}`, - `--set stackdriver.gcloudServiceAccountKeyBase64=${await getPrometheusGcloudServiceAccountKeyBase64( - clusterName, - cloudProvider, - gcloudProject - )}` - ) - - // Metrics prefix for non-ODIS clusters. - if (!context?.startsWith('AZURE_ODIS')) { - params.push( - `--set stackdriver.metricsPrefix=external.googleapis.com/prometheus/${clusterName}` - ) - } - - if (usingGCP) { - const serviceAccountName = getServiceAccountName(clusterName, cloudProvider) - await createPrometheusGcloudServiceAccount(serviceAccountName, gcloudProject) - console.info(serviceAccountName) - const serviceAccountEmail = await getServiceAccountEmail(serviceAccountName) - params.push( - `--set serviceAccount.annotations.'iam\\\.gke\\\.io/gcp-service-account'=${serviceAccountEmail}` - ) - } - } else { - // Stackdriver disabled - params.push(`--set stackdriver.disabled=true`) - } - - // Set scrape job if set for the context - if (context) { - const scrapeJobName = getDynamicEnvVarValue(DynamicEnvVar.PROM_SCRAPE_JOB_NAME, { context }, '') - const scrapeTargets = getDynamicEnvVarValue(DynamicEnvVar.PROM_SCRAPE_TARGETS, { context }, '') - const scrapeLabels = getDynamicEnvVarValue(DynamicEnvVar.PROM_SCRAPE_LABELS, { context }, '') - - if (scrapeJobName !== '') { - params.push(`--set scrapeJob.Name=${scrapeJobName}`) - } - - if (scrapeTargets !== '') { - const targetParams = setHelmArray('scrapeJob.Targets', scrapeTargets.split(',')) - params.push(...targetParams) - } - - if (scrapeLabels !== '') { - const labelParams = setHelmArray('scrapeJob.Labels', scrapeLabels.split(',')) - params.push(...labelParams) - } - } - - return params -} - -async function getPrometheusGcloudServiceAccountKeyBase64( - clusterName: string, - cloudProvider: string, - gcloudProjectName: string -) { - // First check if value already exist in helm release. If so we pass the same value - // and we avoid creating a new key for the service account - const gcloudServiceAccountKeyBase64 = await getPrometheusGcloudServiceAccountKeyBase64FromHelm() - if (gcloudServiceAccountKeyBase64) { - return gcloudServiceAccountKeyBase64 - } else { - // We do not have the service account key in helm so we need to create the SA (if it does not exist) - // and create a new key for the service account in any case - await switchToGCPProject(gcloudProjectName) - const serviceAccountName = getServiceAccountName(clusterName, cloudProvider) - await createPrometheusGcloudServiceAccount(serviceAccountName, gcloudProjectName) - const serviceAccountEmail = await getServiceAccountEmail(serviceAccountName) - const serviceAccountKeyPath = `/tmp/gcloud-key-${serviceAccountName}.json` - await getServiceAccountKey(serviceAccountEmail, serviceAccountKeyPath) - return fs.readFileSync(serviceAccountKeyPath).toString('base64') - } -} - -async function getPrometheusGcloudServiceAccountKeyBase64FromHelm() { - const prometheusInstalled = await outputIncludes( - `helm list -n ${kubeNamespace}`, - `${releaseName}` - ) - if (prometheusInstalled) { - const [output] = await execCmd(`helm get values -n ${kubeNamespace} ${releaseName}`) - const prometheusValues: any = yaml.safeLoad(output) - return prometheusValues.gcloudServiceAccountKeyBase64 - } -} - -// createPrometheusGcloudServiceAccount creates a gcloud service account with a given -// name and the proper permissions for writing metrics to stackdriver -async function createPrometheusGcloudServiceAccount( - serviceAccountName: string, - gcloudProjectName: string -) { - await execCmdWithExitOnFailure(`gcloud config set project ${gcloudProjectName}`) - const accountCreated = await createServiceAccountIfNotExists( - serviceAccountName, - gcloudProjectName - ) - if (accountCreated) { - let serviceAccountEmail = await getServiceAccountEmail(serviceAccountName) - while (!serviceAccountEmail) { - serviceAccountEmail = await getServiceAccountEmail(serviceAccountName) - } - await execCmdWithExitOnFailure( - `gcloud projects add-iam-policy-binding ${gcloudProjectName} --role roles/monitoring.metricWriter --member serviceAccount:${serviceAccountEmail}` - ) - - // Setup workload identity IAM permissions - await setupGKEWorkloadIdentities( - serviceAccountName, - gcloudProjectName, - kubeNamespace, - kubeServiceAccountName - ) - } -} - -function getCloudProviderPrefix(clusterConfig: BaseClusterConfig) { - const prefixByCloudProvider: { [key in CloudProvider]: string } = { - [CloudProvider.AZURE]: 'aks', - [CloudProvider.GCP]: 'gcp', - } - return prefixByCloudProvider[clusterConfig.cloudProvider] -} - -function getServiceAccountName(clusterName: string, cloudProvider: string) { - // Ensure the service account name is within the length restriction - // and ends with an alphanumeric character - return `prometheus-${cloudProvider}-${clusterName}` - .substring(0, 30) - .replace(/[^a-zA-Z0-9]+$/g, '') -} - -export async function installGrafanaIfNotExists( - context?: string, - clusterConfig?: BaseClusterConfig -) { - const grafanaExists = await outputIncludes( - `helm list -A`, - grafanaReleaseName, - `grafana exists, skipping install` - ) - if (!grafanaExists) { - console.info('Installing grafana') - await installGrafana(context, clusterConfig) - } -} - -async function installGrafana(context?: string, clusterConfig?: BaseClusterConfig) { - await helmAddRepoAndUpdate('https://grafana.github.io/helm-charts', 'grafana') - await createNamespaceIfNotExists(kubeNamespace) - return installGenericHelmChart({ - namespace: kubeNamespace, - releaseName: grafanaReleaseName, - chartDir: grafanaHelmRepo, - parameters: await grafanaHelmParameters(context, clusterConfig), - buildDependencies: false, - valuesOverrideFile: '../helm-charts/grafana/values-clabs.yaml', - }) -} - -export async function upgradeGrafana(context?: string, clusterConfig?: BaseClusterConfig) { - await helmAddRepoAndUpdate('https://grafana.github.io/helm-charts', 'grafana') - await createNamespaceIfNotExists(kubeNamespace) - return upgradeGenericHelmChart({ - namespace: kubeNamespace, - releaseName: grafanaReleaseName, - chartDir: grafanaHelmRepo, - parameters: await grafanaHelmParameters(context, clusterConfig), - buildDependencies: false, - // Adding this file and clabs' default values file. - valuesOverrideFile: '../helm-charts/grafana/values-clabs.yaml', - }) -} - -export async function removeGrafanaHelmRelease() { - const grafanaExists = await outputIncludes(`helm list -A`, grafanaReleaseName) - if (grafanaExists) { - console.info('Removing grafana') - await removeGenericHelmChart(grafanaReleaseName, kubeNamespace) - } -} - -async function grafanaHelmParameters(context?: string, clusterConfig?: BaseClusterConfig) { - // Grafana chart is a copy from source. No changes done directly on the chart. - const [_, k8sClusterName] = getK8sContextVars(clusterConfig, context) - const k8sDomainName = fetchEnv(envVar.CLUSTER_DOMAIN_NAME) - // Rename baklavastaging -> baklava - const grafanaUrl = - k8sClusterName !== 'baklavastaging' - ? `${k8sClusterName}-grafana.${k8sDomainName}.org` - : `baklava-grafana.${k8sDomainName}.org` - const values = { - adminPassword: fetchEnv(envVar.GRAFANA_LOCAL_ADMIN_PASSWORD), - 'grafana.ini': { - server: { - root_url: `https://${grafanaUrl}`, - }, - 'auth.google': { - client_id: fetchEnv(envVar.GRAFANA_LOCAL_OAUTH2_CLIENT_ID), - client_secret: fetchEnv(envVar.GRAFANA_LOCAL_OAUTH2_CLIENT_SECRET), - }, - }, - ingress: { - hosts: [grafanaUrl], - tls: [ - { - secretName: `${k8sClusterName}-grafana-tls`, - hosts: [grafanaUrl], - }, - ], - }, - } - - const valuesFile = '/tmp/grafana-values.yaml' - fs.writeFileSync(valuesFile, yaml.safeDump(values)) - - // Adding this file and clabs' default values file. - const params = [`-f ${valuesFile} --version ${grafanaChartVersion}`] - return params -} diff --git a/packages/celotool/src/lib/promtail.ts b/packages/celotool/src/lib/promtail.ts deleted file mode 100644 index 3a4144684..000000000 --- a/packages/celotool/src/lib/promtail.ts +++ /dev/null @@ -1,155 +0,0 @@ -import { createNamespaceIfNotExists } from 'src/lib/cluster' -import { execCmdWithExitOnFailure } from 'src/lib/cmd-utils' -import { envVar, fetchEnv } from 'src/lib/env-utils' -import { - helmAddAndUpdateRepos, - installHelmDiffPlugin, - isCelotoolHelmDryRun, - isCelotoolVerbose, - removeGenericHelmChart, -} from 'src/lib/helm_deploy' -import { BaseClusterConfig, CloudProvider } from 'src/lib/k8s-cluster/base' -import { GCPClusterConfig } from 'src/lib/k8s-cluster/gcp' -import { - createServiceAccountIfNotExists, - getServiceAccountEmail, - setupGKEWorkloadIdentities, -} from 'src/lib/service-account-utils' -import { outputIncludes } from 'src/lib/utils' - -// https://artifacthub.io/packages/helm/grafana/promtail -const helmChartPath = 'grafana/promtail' -const valuesFilePath = '../helm-charts/promtail/values.yaml' -const releaseName = 'promtail' -const kubeNamespace = 'prometheus' -const kubeServiceAccountName = 'gcp-promtail-loki-grafana' -const promtailImageTag = '2.3.0' -const chartVersion = '3.8.2' - -export async function installPromtailIfNotExists(clusterConfig?: BaseClusterConfig) { - const promtailExists = await outputIncludes( - `helm list -n ${kubeNamespace}`, - releaseName, - `${releaseName} exists, skipping install` - ) - if (!promtailExists) { - console.info(`Installing ${releaseName}`) - await installPromtail(clusterConfig) - } -} - -async function installPromtail(clusterConfig?: BaseClusterConfig) { - await helmAddAndUpdateRepos() - await createNamespaceIfNotExists(kubeNamespace) - - const cmd = await buildHelmUpgradeCmd(await helmParameters(clusterConfig)) - await execCmdWithExitOnFailure(cmd, {}, isCelotoolVerbose()) -} - -export async function removePromtail() { - await removeGenericHelmChart(releaseName, kubeNamespace) -} - -export async function upgradePromtail(clusterConfig?: BaseClusterConfig) { - const cmd = await buildHelmUpgradeCmd(await helmParameters(clusterConfig)) - await execCmdWithExitOnFailure(cmd, {}, isCelotoolVerbose()) -} - -async function helmParameters(clusterConfig?: BaseClusterConfig) { - const params = [] - - // Find which cloud provider is in use - const cloudProvider = clusterConfig ? clusterConfig.cloudProvider : CloudProvider.GCP - - switch (cloudProvider) { - case CloudProvider.GCP: - let gcpProjectName, clusterName - if (clusterConfig) { - const configGCP = clusterConfig as GCPClusterConfig - gcpProjectName = configGCP!.projectName - clusterName = configGCP!.clusterName - } else { - gcpProjectName = fetchEnv(envVar.TESTNET_PROJECT_NAME) - clusterName = fetchEnv(envVar.KUBERNETES_CLUSTER_NAME) - } - - const serviceAccountName = await createPromtailGcloudServiceAccount( - gcpProjectName, - clusterName - ) - const serviceAccountEmail = await getServiceAccountEmail(serviceAccountName) - - params.push( - `--set serviceAccount.annotations.'iam\\\.gke\\\.io/gcp-service-account'=${serviceAccountEmail}` - ) - params.push(`--set extraArgs[0]='-client.external-labels=cluster_name=${clusterName}'`) - break - - case CloudProvider.AZURE: - // Adding cluster_name label - params.push( - `--set extraArgs[0]='-client.external-labels=cluster_name=${clusterConfig?.clusterName}'` - ) - break - } - - const user = fetchEnv(envVar.LOKI_USERNAME) - const key = fetchEnv(envVar.LOKI_KEY) - const url = fetchEnv(envVar.LOKI_URL) - params.push(`--set config.lokiAddress=https://${user}:${key}@${url}`) - params.push(`--set promtail.imageTag=${promtailImageTag}`) - params.push(`--version=${chartVersion}`) - - return params -} - -async function createPromtailGcloudServiceAccount(gcpProjectName: string, clusterName: string) { - // Create a new GCP Service Account - const serviceAccountName = getServiceAccountName(clusterName, 'gcp') - - const accountCreated = await createServiceAccountIfNotExists( - serviceAccountName, - gcpProjectName, - 'Loki/Promtail service account to push logs to Grafana Cloud' - ) - - if (accountCreated) { - // Setup workload identity IAM permissions - await setupGKEWorkloadIdentities( - serviceAccountName, - gcpProjectName, - kubeNamespace, - kubeServiceAccountName - ) - } - - return serviceAccountName -} - -// TODO: refactor with the function in prometheus -function getServiceAccountName(clusterName: string, cloudProvider: string) { - return `promtail-${cloudProvider}-${clusterName}`.substring(0, 30).replace(/[^a-zA-Z0-9]+$/g, '') -} - -async function buildHelmUpgradeCmd(params: string[]) { - if (isCelotoolHelmDryRun()) { - await installHelmDiffPlugin() - } - - let cmd = `helm ${ - isCelotoolHelmDryRun() ? 'diff -C 5' : '' - } upgrade --install ${releaseName} ${helmChartPath} \ - -n ${kubeNamespace} \ - -f ${valuesFilePath} \ - ${params.join(' ')}` - - if (isCelotoolVerbose()) { - cmd += ' --debug' - if (isCelotoolHelmDryRun()) { - // The promtail config is a k8s secret. - cmd += ' --show-secrets' - } - } - - return cmd -} diff --git a/packages/celotool/src/lib/pubsub.ts b/packages/celotool/src/lib/pubsub.ts deleted file mode 100644 index b3597a05c..000000000 --- a/packages/celotool/src/lib/pubsub.ts +++ /dev/null @@ -1,56 +0,0 @@ -import PubSub from '@google-cloud/pubsub' - -export const createClient = (credentials?: any) => { - // @ts-ignore-next-line - return new PubSub.v1.SubscriberClient({ credentials }) -} - -export const buildSubscriptionName = (envName: string, purpose: string) => { - return `${envName}-${purpose}` -} - -export const createSubscription = async ( - client: any, - projectID: string, - topic: string, - subscriptionName: string -) => { - const formattedName = client.subscriptionPath(projectID, subscriptionName) - const formattedTopic = client.topicPath(projectID, topic) - - const request = { - name: formattedName, - topic: formattedTopic, - } - const [subscriptionInfo] = await client.createSubscription(request) - - return subscriptionInfo -} - -export const deleteSubscription = async ( - client: any, - projectID: string, - subscriptionName: string -) => { - const formattedName = client.subscriptionPath(projectID, subscriptionName) - - await client.deleteSubscription({ subscription: formattedName }) - - return true -} - -export const createStreamingPull = ( - client: any, - projectID: string, - subscriptionName: string, - // tslint:disable-next-line: ban-types - handler: Function -) => { - const stream = client.streamingPull().on('data', handler) - const formattedName = client.subscriptionPath(projectID, subscriptionName) - const request = { - subscription: formattedName, - streamAckDeadlineSeconds: 10, - } - stream.write(request) -} diff --git a/packages/celotool/src/lib/pumba.ts b/packages/celotool/src/lib/pumba.ts deleted file mode 100644 index 4ecd35145..000000000 --- a/packages/celotool/src/lib/pumba.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { makeHelmParameters } from 'src/lib/helm_deploy' -import { envVar, fetchEnv } from './env-utils' - -export function helmReleaseName(celoEnv: string) { - return celoEnv + '-pumba' -} - -export const helmChartDir = '../helm-charts/pumba' - -export function helmParameters() { - return makeHelmParameters({ - 'pumba.interval': fetchEnv(envVar.CHAOS_TEST_INTERVAL), - 'pumba.duration': fetchEnv(envVar.CHAOS_TEST_DURATION), - 'pumba.networkDelay': fetchEnv(envVar.CHAOS_TEST_NETWORK_DELAY), - 'pumba.networkJitter': fetchEnv(envVar.CHAOS_TEST_NETWORK_JITTER), - 'pumba.networkLoss': fetchEnv(envVar.CHAOS_TEST_NETWORK_LOSS), - 'pumba.networkRate': fetchEnv(envVar.CHAOS_TEST_NETWORK_RATE), - }) -} diff --git a/packages/celotool/src/lib/service-account-utils.ts b/packages/celotool/src/lib/service-account-utils.ts deleted file mode 100644 index d475d1637..000000000 --- a/packages/celotool/src/lib/service-account-utils.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { execCmdAndParseJson, execCmdWithExitOnFailure } from './cmd-utils' -import { isCelotoolHelmDryRun } from './helm_deploy' -import { switchToGCPProject, switchToProjectFromEnv } from './utils' - -// createServiceAccountIfNotExists creates a service account with the given name -// if it does not exist. Returns if the account was created. -export async function createServiceAccountIfNotExists( - name: string, - gcloudProject?: string, - description?: string -) { - if (gcloudProject !== undefined) { - await switchToGCPProject(gcloudProject) - } else { - await switchToProjectFromEnv() - } - // TODO: add permissions for cloudsql editor to service account - const serviceAccounts = await execCmdAndParseJson( - `gcloud iam service-accounts list --filter "displayName:${name}" --quiet --format json` - ) - const serviceAccountExists = serviceAccounts.some((account: any) => account.displayName === name) - if (!serviceAccountExists) { - let cmd = `gcloud iam service-accounts create ${name} --display-name="${name}" ` - if (description) { - cmd = cmd.concat(`--description="${description}"`) - } - if (isCelotoolHelmDryRun()) { - console.info(`This would run the following command:\n${cmd}\n`) - } else { - await execCmdWithExitOnFailure(cmd) - } - } - return !serviceAccountExists -} - -// getServiceAccountEmail returns the email of the service account with the -// given name -export async function getServiceAccountEmail(serviceAccountName: string) { - const [output] = await execCmdWithExitOnFailure( - `gcloud iam service-accounts list --filter="displayName<=${serviceAccountName} AND displayName>=${serviceAccountName}" --format='value[terminator=""](email)'` - ) - return output -} - -export function getServiceAccountKey(serviceAccountEmail: string, keyPath: string) { - return execCmdWithExitOnFailure( - `gcloud iam service-accounts keys create ${keyPath} --iam-account ${serviceAccountEmail}` - ) -} - -// Used for Prometheus and Promtail/Loki -// https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity -export async function setupGKEWorkloadIdentities( - serviceAccountName: string, - gcloudProjectName: string, - kubeNamespace: string, - kubeServiceAccountName: string -) { - // Only grant access to GCE API to Prometheus or Promtail SA deployed in GKE - if (!serviceAccountName.includes('gcp')) { - return - } - - const serviceAccountEmail = await getServiceAccountEmail(serviceAccountName) - - // Allow the Kubernetes service account to impersonate the Google service account - const roleIamWorkloadIdentityUserCmd = `gcloud iam --project ${gcloudProjectName} service-accounts add-iam-policy-binding \ - --role roles/iam.workloadIdentityUser \ - --member "serviceAccount:${gcloudProjectName}.svc.id.goog[${kubeNamespace}/${kubeServiceAccountName}]" \ - ${serviceAccountEmail}` - - if (isCelotoolHelmDryRun()) { - console.info(`This would run the following: ${roleIamWorkloadIdentityUserCmd}\n`) - } else { - await execCmdWithExitOnFailure(roleIamWorkloadIdentityUserCmd) - } -} diff --git a/packages/celotool/src/lib/testnet-utils.ts b/packages/celotool/src/lib/testnet-utils.ts deleted file mode 100644 index ae1b838f8..000000000 --- a/packages/celotool/src/lib/testnet-utils.ts +++ /dev/null @@ -1,216 +0,0 @@ -import { StaticNodeUtils } from '@celo/network-utils' -import { GenesisBlocksGoogleStorageBucketName } from '@celo/network-utils/lib/genesis-block-utils' -import { Storage } from '@google-cloud/storage' -import * as fs from 'fs' -import fetch from 'node-fetch' -import * as path from 'path' -import { retryCmd } from '../lib/utils' -import { execCmdWithExitOnFailure } from './cmd-utils' -import { getGenesisGoogleStorageUrl } from './endpoints' -import { envVar, fetchEnvOrFallback, getEnvFile } from './env-utils' -import { ensureAuthenticatedGcloudAccount } from './gcloud_utils' -import { getBootnodeEnode, getEnodesWithExternalIPAddresses } from './geth' -const genesisBlocksBucketName = GenesisBlocksGoogleStorageBucketName -const staticNodesBucketName = StaticNodeUtils.getStaticNodesGoogleStorageBucketName() -// Someone has taken env_files and I don't even has permission to modify it :/ -// See files in this bucket using `$ gsutil ls gs://env_config_files` -const envBucketName = 'env_config_files' -const bootnodesBucketName = 'env_bootnodes' - -// uploads genesis block, static nodes, env file, and bootnode to GCS -export async function uploadTestnetInfoToGoogleStorage(networkName: string) { - await uploadTestnetStaticNodesToGoogleStorage(networkName) - await uploadBootnodeToGoogleStorage(networkName) - await uploadEnvFileToGoogleStorage(networkName) -} - -export async function uploadGenesisBlockToGoogleStorage(networkName: string, genesis: string) { - console.info(`\nUploading genesis block for ${networkName} to Google cloud storage`) - console.debug(`Genesis block is ${genesis} \n`) - await uploadDataToGoogleStorage( - genesis, - genesisBlocksBucketName, - networkName, - true, - 'application/json' - ) -} - -export async function getGenesisBlockFromGoogleStorage(networkName: string) { - const resp = await fetch(getGenesisGoogleStorageUrl(networkName)) - return JSON.stringify(await resp.json()) -} - -// This will throw an error if it fails to upload. -// Intended to be used for deploying testnets, not forno full nodes. -export async function uploadTestnetStaticNodesToGoogleStorage(networkName: string) { - console.info(`\nUploading static nodes for ${networkName} to Google cloud storage...`) - // Get node json file - const nodesData: string[] | null = await retryCmd(() => - getEnodesWithExternalIPAddresses(networkName) - ) - if (nodesData === null) { - throw new Error('Fail to get static nodes information') - } - return uploadStaticNodesToGoogleStorage(networkName, nodesData) -} - -export async function uploadStaticNodesToGoogleStorage(fileName: string, enodes: string[]) { - const json = JSON.stringify(enodes) - console.debug(`${fileName} static nodes are ${json}\n`) - await uploadDataToGoogleStorage(json, staticNodesBucketName, fileName, true, 'application/json') -} - -export async function uploadBootnodeToGoogleStorage(networkName: string) { - console.info(`\nUploading bootnode for ${networkName} to Google Cloud Storage...`) - const [bootnodeEnode] = await retryCmd(() => getBootnodeEnode(networkName)) - if (!bootnodeEnode) { - throw new Error('Failed to get bootnode enode') - } - // for now there is always only one bootnodde - console.info('Bootnode enode:', bootnodeEnode) - await uploadDataToGoogleStorage( - bootnodeEnode, - bootnodesBucketName, - networkName, - true, // make it public - 'text/plain' - ) -} - -export async function uploadEnvFileToGoogleStorage(networkName: string) { - const envFileName = getEnvFile(networkName) - const userInfo = `${await getGoogleCloudUserInfo()}` - const repo = await getGitRepoName() - const commitHash = await getCommitHash() - - console.info( - `\nUploading Env file ${envFileName} for network ${networkName} to Google cloud storage: ` + - `gs://${envBucketName}/${networkName}` - ) - const envFileData = fs.readFileSync(getEnvFile(networkName)).toString() - const metaData = - `# .env file for network "${networkName}"\n` + - `# Last modified by "${userInfo}"\n` + - `# Last modified on on ${Date()}\n` + - `# Base commit: "https://github.com/${repo}/commit/${commitHash}"\n` - const fullData = metaData + '\n' + envFileData - await uploadDataToGoogleStorage( - fullData, - envBucketName, - networkName, - false /* keep file private */, - 'text/plain' - ) -} - -async function getGoogleCloudUserInfo(): Promise { - const cmd = 'gcloud config get-value account' - const stdout = (await execCmdWithExitOnFailure(cmd))[0] - return stdout.trim() -} - -async function getGitRepoName(): Promise { - const cmd = 'git config --get remote.origin.url' - let stdout = '' - try { - stdout = (await execCmdWithExitOnFailure(cmd))[0].trim() - stdout = stdout.split(':')[1] - if (stdout.endsWith('.git')) { - stdout = stdout.substring(0, stdout.length - '.git'.length) - } - } catch (error) { - // Not running from a git folder - stdout = 'celo-monorepo' - } - - return stdout -} - -async function getCommitHash(): Promise { - try { - const cmd = 'git show | head -n 1' - const stdout = (await execCmdWithExitOnFailure(cmd))[0] - return stdout.split(' ')[1].trim() - } catch (error) { - // Not running from a git folder - return 'no-commmit-hash' - } -} - -// Writes data to a temporary file & uploads it to GCS -export function uploadDataToGoogleStorage( - data: any, - googleStorageBucketName: string, - googleStorageFileName: string, - makeFileWorldReadable: boolean, - contentType: string -) { - const localTmpFilePath = `/tmp/${googleStorageBucketName}-${googleStorageFileName}` - // @ts-ignore The expected type of this is not accurate - fs.mkdirSync(path.dirname(localTmpFilePath), { - recursive: true, - }) - fs.writeFileSync(localTmpFilePath, data) - return uploadFileToGoogleStorage( - localTmpFilePath, - googleStorageBucketName, - googleStorageFileName, - makeFileWorldReadable, - contentType - ) -} - -// TODO(yerdua): make this communicate or handle auth issues reasonably. Ideally, -// it should catch an auth error and tell the user to login with `gcloud auth login`. -// So, if you run into an error that says something about being unauthorized, -// copy and paste this into your terminal: gcloud auth login -// One can browse these files at https://console.cloud.google.com/storage/browser -export async function uploadFileToGoogleStorage( - localFilePath: string, - googleStorageBucketName: string, - googleStorageFileName: string, - makeFileWorldReadable: boolean, - contentType: string -) { - await ensureAuthenticatedGcloudAccount() - const storage = new Storage() - await storage.bucket(googleStorageBucketName).upload(localFilePath, { - destination: googleStorageFileName, - contentType, - metadata: { - cacheControl: 'private', - }, - }) - - if (makeFileWorldReadable) { - // set the permission to be world-readable - await storage.bucket(googleStorageBucketName).file(googleStorageFileName).acl.add({ - entity: 'allUsers', - role: storage.acl.READER_ROLE, - }) - } -} - -// Reads the envVar VALIDATOR_PROXY_COUNTS, which indicates how many validators -// have a certain number of proxies in the format: -// <# of validators>:;<# of validators>:;... -// For example, VALIDATOR_PROXY_COUNTS='1:0,2:1,3:2' will give [0,1,1,2,2,2] -export function getProxiesPerValidator() { - const arr = [] - const valProxyCountsStr = fetchEnvOrFallback(envVar.VALIDATOR_PROXY_COUNTS, '') - const splitValProxyCountStrs = valProxyCountsStr.split(',').filter((counts) => counts) - for (const valProxyCount of splitValProxyCountStrs) { - const [valCountStr, proxyCountStr] = valProxyCount.split(':') - const valCount = parseInt(valCountStr, 10) - const proxyCount = parseInt(proxyCountStr, 10) - for (let i = 0; i < valCount; i++) { - arr.push(proxyCount) - } - } - return arr -} - -export function getProxyName(celoEnv: string, validatorIndex: number, proxyIndex: number) { - return `${celoEnv}-validators-${validatorIndex}-proxy-${proxyIndex}` -} diff --git a/packages/celotool/src/lib/tracer-tool.ts b/packages/celotool/src/lib/tracer-tool.ts deleted file mode 100644 index 987f78f23..000000000 --- a/packages/celotool/src/lib/tracer-tool.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { getEnodesAddresses } from 'src/lib/geth' -import { - installGenericHelmChart, - removeGenericHelmChart, - upgradeGenericHelmChart, -} from 'src/lib/helm_deploy' -import { envVar, fetchEnv } from './env-utils' - -const chartDir = '../helm-charts/tracer-tool/' - -function releaseName(celoEnv: string) { - return `${celoEnv}-tracer-tool` -} - -export async function installHelmChart(celoEnv: string) { - await installGenericHelmChart({ - namespace: celoEnv, - releaseName: releaseName(celoEnv), - chartDir, - parameters: await helmParameters(celoEnv), - }) -} - -export async function upgradeHelmChart(celoEnv: string) { - await upgradeGenericHelmChart({ - namespace: celoEnv, - releaseName: releaseName(celoEnv), - chartDir, - parameters: await helmParameters(celoEnv), - }) -} - -export async function removeHelmRelease(celoEnv: string) { - await removeGenericHelmChart(releaseName(celoEnv), celoEnv) -} - -async function helmParameters(celoEnv: string) { - const enodes = await getEnodesAddresses(celoEnv) - const b64EnodesJSON = Buffer.from(JSON.stringify(enodes, null, 0)).toString('base64') - - return [ - `--namespace ${celoEnv}`, - `--set imageRepository=${fetchEnv(envVar.CELOTOOL_DOCKER_IMAGE_REPOSITORY)}`, - `--set imageTag=${fetchEnv(envVar.CELOTOOL_DOCKER_IMAGE_TAG)}`, - `--set environment=${celoEnv}`, - `--set enodes="${b64EnodesJSON}"`, - ] -} diff --git a/packages/celotool/src/lib/transaction-metrics-exporter.ts b/packages/celotool/src/lib/transaction-metrics-exporter.ts deleted file mode 100644 index 4b79a2325..000000000 --- a/packages/celotool/src/lib/transaction-metrics-exporter.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { envVar, fetchEnv, fetchEnvOrFallback } from 'src/lib/env-utils' -import { - installGenericHelmChart, - removeGenericHelmChart, - upgradeGenericHelmChart, -} from 'src/lib/helm_deploy' - -const chartDir = '../helm-charts/transaction-metrics-exporter/' - -function releaseName(celoEnv: string, suffix: string) { - return `${celoEnv}-transaction-metrics-exporter-${suffix}` -} - -export async function installHelmChart(celoEnv: string) { - const suffix = fetchEnvOrFallback(envVar.TRANSACTION_METRICS_EXPORTER_SUFFIX, '1') - await installGenericHelmChart({ - namespace: celoEnv, - releaseName: releaseName(celoEnv, suffix), - chartDir, - parameters: await helmParameters(celoEnv), - }) -} - -export async function upgradeHelmChart(celoEnv: string) { - const suffix = fetchEnvOrFallback(envVar.TRANSACTION_METRICS_EXPORTER_SUFFIX, '1') - await upgradeGenericHelmChart({ - namespace: celoEnv, - releaseName: releaseName(celoEnv, suffix), - chartDir, - parameters: await helmParameters(celoEnv), - }) -} - -export async function removeHelmRelease(celoEnv: string) { - const suffix = fetchEnvOrFallback(envVar.TRANSACTION_METRICS_EXPORTER_SUFFIX, '1') - await removeGenericHelmChart(releaseName(celoEnv, suffix), celoEnv) -} - -async function helmParameters(celoEnv: string) { - const suffix = fetchEnvOrFallback(envVar.TRANSACTION_METRICS_EXPORTER_SUFFIX, '1') - const params = [ - `--namespace ${celoEnv}`, - `--set environment="${celoEnv}"`, - `--set imageRepository="${fetchEnv( - envVar.TRANSACTION_METRICS_EXPORTER_DOCKER_IMAGE_REPOSITORY - )}"`, - `--set imageTag="${fetchEnv(envVar.TRANSACTION_METRICS_EXPORTER_DOCKER_IMAGE_TAG)}"`, - `--set deploymentSuffix=${suffix}`, - `--set fromBlock=${fetchEnvOrFallback(envVar.TRANSACTION_METRICS_EXPORTER_FROM_BLOCK, '0')}`, - `--set toBlock=${fetchEnvOrFallback(envVar.TRANSACTION_METRICS_EXPORTER_FROM_BLOCK, '')}`, - `--set blockInterval=${fetchEnvOrFallback( - envVar.TRANSACTION_METRICS_EXPORTER_BLOCK_INTERVAL, - '1' - )}`, - `--set watchAddress=${fetchEnvOrFallback( - envVar.TRANSACTION_METRICS_EXPORTER_WATCH_ADDRESS, - '' - )}`, - ] - return params -} diff --git a/packages/celotool/src/lib/utils.ts b/packages/celotool/src/lib/utils.ts deleted file mode 100644 index 40e4bf74b..000000000 --- a/packages/celotool/src/lib/utils.ts +++ /dev/null @@ -1,96 +0,0 @@ -import sleep from 'sleep-promise' -import yargs from 'yargs' -import { switchToClusterFromEnv } from './cluster' -import { execCmdWithExitOnFailure } from './cmd-utils' -import { envVar, fetchEnv } from './env-utils' -import { retrieveIPAddress } from './helm_deploy' - -export async function outputIncludes(cmd: string, matchString: string, matchMessage?: string) { - const [stdout] = await execCmdWithExitOnFailure(cmd) - if (stdout.includes(matchString)) { - if (matchMessage) { - console.info(matchMessage) - } - return true - } - return false -} - -export async function retrieveTxNodeIpAddress(celoEnv: string, txNodeIndex: number) { - return retrieveIPAddress(`${celoEnv}-tx-nodes-${txNodeIndex}`) -} - -export async function getVerificationPoolConfig(celoEnv: string) { - await switchToClusterFromEnv(celoEnv) - - const ip = await retrieveTxNodeIpAddress(celoEnv, 0) - - return { - testnetId: fetchEnv('NETWORK_ID'), - txIP: ip, - txPort: '8545', - } -} - -export async function switchToGCPProject(projectName: string) { - const [currentProject] = await execCmdWithExitOnFailure('gcloud config get-value project') - - if (currentProject !== projectName) { - await execCmdWithExitOnFailure(`gcloud config set project ${projectName}`) - } -} - -export async function switchToProjectFromEnv() { - const expectedProject = fetchEnv(envVar.TESTNET_PROJECT_NAME) - await switchToGCPProject(expectedProject) -} - -export function addCeloGethMiddleware(argv: yargs.Argv) { - return argv - .option('geth-dir', { - type: 'string', - description: 'path to geth repository', - demand: 'Please, specify the path to geth directory, where the binary could be found', - }) - .option('data-dir', { - type: 'string', - description: 'path to datadir', - demand: 'Please, specify geth datadir', - }) -} - -// Some tools require hex address to be preceeded by 0x, some don't. -// Therefore, we try to be conservative and accept only the addresses prefixed by 0x as valid. -export const validateAccountAddress = (address: string) => { - return address !== null && address.toLowerCase().startsWith('0x') && address.length === 42 // 0x followed by 40 hex-chars -} - -export const ensure0x = (hexstr: string) => (hexstr.startsWith('0x') ? hexstr : '0x' + hexstr) -export const strip0x = (hexstr: string) => (hexstr.startsWith('0x') ? hexstr.slice(2) : hexstr) - -export async function retryCmd( - cmd: () => Promise, - numAttempts: number = 100, - maxTimeoutMs: number = 15000 -) { - for (let i = 1; i <= numAttempts; i++) { - try { - const result = await cmd() - return result - } catch (error) { - const sleepTimeBasisInMs = 1000 - const sleepTimeInMs = Math.min(sleepTimeBasisInMs * Math.pow(2, i), maxTimeoutMs) - console.warn( - `${new Date().toLocaleTimeString()} Retry attempt: ${i}/${numAttempts}, ` + - `retry after sleeping for ${sleepTimeInMs} milli-seconds`, - error - ) - await sleep(sleepTimeInMs) - } - } - throw Error(`Retried ${numAttempts} without any successes`) -} - -export const stringToBoolean = (myString: string) => { - return myString.toLowerCase() === 'true' -} diff --git a/packages/celotool/src/lib/voting-bot.ts b/packages/celotool/src/lib/voting-bot.ts deleted file mode 100644 index e16cb1250..000000000 --- a/packages/celotool/src/lib/voting-bot.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { ContractKit, newKitFromWeb3 } from '@celo/contractkit' -import { getFornoUrl } from 'src/lib/endpoints' -import { envVar, fetchEnv } from 'src/lib/env-utils' -import { AccountType, getPrivateKeysFor } from 'src/lib/generate_utils' -import { installGenericHelmChart, removeGenericHelmChart } from 'src/lib/helm_deploy' -import { ensure0x } from 'src/lib/utils' -import Web3 from 'web3' - -const web3 = new Web3() - -const helmChartPath = '../helm-charts/voting-bot' - -export async function installHelmChart(celoEnv: string, excludedGroups?: string[]) { - const params = await helmParameters(celoEnv, excludedGroups) - console.info(params) - return installGenericHelmChart({ - namespace: celoEnv, - releaseName: releaseName(celoEnv), - chartDir: helmChartPath, - parameters: params, - }) -} -export async function removeHelmRelease(celoEnv: string) { - await removeGenericHelmChart(releaseName(celoEnv), celoEnv) -} - -export async function setupVotingBotAccounts(celoEnv: string) { - const fornoUrl = getFornoUrl(celoEnv) - const mnemonic = fetchEnv(envVar.MNEMONIC) - const numBotAccounts = parseInt(fetchEnv(envVar.VOTING_BOTS), 10) - - const kit: ContractKit = newKitFromWeb3(new Web3(fornoUrl)) - const goldToken = await kit.contracts.getGoldToken() - const lockedGold = await kit.contracts.getLockedGold() - const accounts = await kit.contracts.getAccounts() - - const botsWithoutGold: string[] = [] - - for (const key of getPrivateKeysFor(AccountType.VOTING_BOT, mnemonic, numBotAccounts)) { - const botAccount = ensure0x(web3.eth.accounts.privateKeyToAccount(key).address) - const goldBalance = await goldToken.balanceOf(botAccount) - if (goldBalance.isZero()) { - botsWithoutGold.push(botAccount) - continue - } - - kit.connection.addAccount(key) - - if (!(await accounts.isAccount(botAccount))) { - const registerTx = await accounts.createAccount() - await registerTx.sendAndWaitForReceipt({ from: botAccount }) - } - - const amountLocked = await lockedGold.getAccountTotalLockedGold(botAccount) - if (amountLocked.isZero()) { - const tx = await lockedGold.lock() - const amountToLock = goldBalance.multipliedBy(0.99).toFixed(0) - - await tx.sendAndWaitForReceipt({ - to: lockedGold.address, - value: amountToLock, - from: botAccount, - }) - console.info(`Locked gold for ${botAccount}`) - } - } - if (botsWithoutGold.length > 0) { - throw new Error(`These bot accounts have no gold. Faucet them, and retry: ${botsWithoutGold}`) - } - console.info('Finished/confirmed setup of voting bot accounts') - - kit.connection.stop() -} - -function helmParameters(celoEnv: string, excludedGroups?: string[]) { - const params = [ - `--set celoProvider=${getFornoUrl(celoEnv)}`, - `--set cronSchedule="${fetchEnv(envVar.VOTING_BOT_CRON_SCHEDULE)}"`, - `--set domain.name=${fetchEnv(envVar.CLUSTER_DOMAIN_NAME)}`, - `--set environment=${celoEnv}`, - `--set imageRepository=${fetchEnv(envVar.CELOTOOL_DOCKER_IMAGE_REPOSITORY)}`, - `--set imageTag=${fetchEnv(envVar.CELOTOOL_DOCKER_IMAGE_TAG)}`, - `--set mnemonic="${fetchEnv(envVar.MNEMONIC)}"`, - `--set votingBot.changeBaseline="${fetchEnv(envVar.VOTING_BOT_CHANGE_BASELINE)}"`, - `--set votingBot.count=${fetchEnv(envVar.VOTING_BOTS)}`, - `--set votingBot.exploreProbability="${fetchEnv(envVar.VOTING_BOT_EXPLORE_PROBABILITY)}"`, - `--set votingBot.scoreSensitivity="${fetchEnv(envVar.VOTING_BOT_SCORE_SENSITIVITY)}"`, - `--set votingBot.wakeProbability="${fetchEnv(envVar.VOTING_BOT_WAKE_PROBABILITY)}"`, - ] - - if (excludedGroups && excludedGroups.length > 0) { - params.push(`--set votingBot.excludedGroups="${excludedGroups.join('\\,')}"`) - } - return params -} - -function releaseName(celoEnv: string) { - return `${celoEnv}-voting-bot` -} diff --git a/packages/celotool/src/lib/wallet-connect.ts b/packages/celotool/src/lib/wallet-connect.ts deleted file mode 100644 index 83564d151..000000000 --- a/packages/celotool/src/lib/wallet-connect.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { createNamespaceIfNotExists } from 'src/lib/cluster' -import { - installGenericHelmChart, - makeHelmParameters, - removeGenericHelmChart, - upgradeGenericHelmChart, -} from 'src/lib/helm_deploy' -import { envVar, fetchEnv } from './env-utils' - -const releaseName = 'walletconnect' -const releaseNamespace = 'walletconnect' - -export const helmChartDir = '../helm-charts/wallet-connect' - -export async function installWalletConnect() { - await createNamespaceIfNotExists(releaseNamespace) - await installGenericHelmChart({ - namespace: releaseNamespace, - releaseName, - chartDir: helmChartDir, - parameters: helmParameters(), - }) -} - -export async function upgradeWalletConnect() { - await upgradeGenericHelmChart({ - namespace: releaseNamespace, - releaseName, - chartDir: helmChartDir, - parameters: helmParameters(), - }) -} - -export async function removeWalletConnect() { - await removeGenericHelmChart(releaseName, releaseNamespace) -} - -export function helmParameters() { - return makeHelmParameters({ - 'domain.name': fetchEnv(envVar.CLUSTER_DOMAIN_NAME), - 'walletconnect.image.repository': fetchEnv(envVar.WALLET_CONNECT_IMAGE_REPOSITORY), - 'walletconnect.image.tag': fetchEnv(envVar.WALLET_CONNECT_IMAGE_TAG), - 'redis.cluster.enabled': fetchEnv(envVar.WALLET_CONNECT_REDIS_CLUSTER_ENABLED), - 'redis.cluster.usePassword': fetchEnv(envVar.WALLET_CONNECT_REDIS_CLUSTER_USEPASSWORD), - }) -} diff --git a/packages/celotool/src/types.d.ts b/packages/celotool/src/types.d.ts deleted file mode 100644 index cb40e33c9..000000000 --- a/packages/celotool/src/types.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -declare module 'web3-utils' -declare module 'country-data' -declare module 'bip39' { - function mnemonicToSeedSync(mnemonic: string): Buffer -} -declare module 'read-last-lines' { - namespace readLastLines { - function read(inputFilePath: string, maxLineCount: number, encoding?: string): Promise - } - export = readLastLines -} diff --git a/packages/celotool/stakeoff_grants.json b/packages/celotool/stakeoff_grants.json deleted file mode 100644 index 67cb8cf38..000000000 --- a/packages/celotool/stakeoff_grants.json +++ /dev/null @@ -1,2162 +0,0 @@ -[ - { - "identifier": "0x0f0b8b43084d3aa8a05d60922F8a2791FB603970", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x0f0b8b43084d3aa8a05d60922F8a2791FB603970", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x57a5fddadb1d26d0558a55bd11e17f16ebcfbbcb", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x57a5fddadb1d26d0558a55bd11e17f16ebcfbbcb", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x6bd60aa42b900f7a5608d4dff5b406e503924c24", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x6bd60aa42b900f7a5608d4dff5b406e503924c24", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x2E5b1E0ebbAbBf74b2D13876e027a42939892610", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10702, - "revocable": false, - "beneficiary": "0x2E5b1E0ebbAbBf74b2D13876e027a42939892610", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x4a2859423ad40C9d2E2C4CC677c28b04eF471578", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x4a2859423ad40C9d2E2C4CC677c28b04eF471578", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xc7040c4DA590E8F0F4d46454AC7c3C82603BaA66", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xc7040c4DA590E8F0F4d46454AC7c3C82603BaA66", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xa087388376f1ebe368e3ae22d630146319410082", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10402, - "revocable": false, - "beneficiary": "0xa087388376f1ebe368e3ae22d630146319410082", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x1223e6fd91058c49264f597ca33e25e99d6de957", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x1223e6fd91058c49264f597ca33e25e99d6de957", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x73dfb47feb4fa1536eb7d54386add730b8fe0235", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x73dfb47feb4fa1536eb7d54386add730b8fe0235", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xf588c86d6555cb264733b97001d28e07279912e2", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xf588c86d6555cb264733b97001d28e07279912e2", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x5d4aeaf81a25a590fac7215851a5541e6239faf7", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 20202, - "revocable": false, - "beneficiary": "0x5d4aeaf81a25a590fac7215851a5541e6239faf7", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xb3Ba92Ab0E7F52E931D9773ab755bF01a0ba3074", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 20002, - "revocable": false, - "beneficiary": "0xb3Ba92Ab0E7F52E931D9773ab755bF01a0ba3074", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xf2e7D6f720B266Bceef81E65388Aebc7D29d1951", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xf2e7D6f720B266Bceef81E65388Aebc7D29d1951", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x584a380b07851A6cf53Fb9F449616dC8A840062b", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x584a380b07851A6cf53Fb9F449616dC8A840062b", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xE2269F2973c11Cd6D9976B04445390Ae32BCa483", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xE2269F2973c11Cd6D9976B04445390Ae32BCa483", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xDE84076a698635151C8237e6d1d6Dc1133703263", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xDE84076a698635151C8237e6d1d6Dc1133703263", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xA588dB154AeDB5D15d765c27b359417255478c72", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xA588dB154AeDB5D15d765c27b359417255478c72", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xE267D978037B89db06C6a5FcF82fAd8297E290ff", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xE267D978037B89db06C6a5FcF82fAd8297E290ff", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x4d82BfC8823a4F3AF82B0AdE52ff3e2d74A04757", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 30002, - "revocable": false, - "beneficiary": "0x4d82BfC8823a4F3AF82B0AdE52ff3e2d74A04757", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x221370e066ab3de1f6130731a1a0e992954ed1a4", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x221370e066ab3de1f6130731a1a0e992954ed1a4", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x4EA01c7F19F64bE2771Ad91568FB01b745637fc9", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x4EA01c7F19F64bE2771Ad91568FB01b745637fc9", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x17787195Df7605290AbB400B19Aa562F3e9E5719", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x17787195Df7605290AbB400B19Aa562F3e9E5719", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x0F96b40F89E6b4690Ddb94dEc4b428Ac31538561", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x0F96b40F89E6b4690Ddb94dEc4b428Ac31538561", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xde8804E1022b7AcE305fCaB28F1ff85DfDc2730e", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xde8804E1022b7AcE305fCaB28F1ff85DfDc2730e", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x861d6466a08BF0E948c57B762DB0dE240E083672", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 20002, - "revocable": false, - "beneficiary": "0x861d6466a08BF0E948c57B762DB0dE240E083672", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x22f22c38C5148f58086b937238c101a0CAEF9DA3", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x22f22c38C5148f58086b937238c101a0CAEF9DA3", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x3Da0f75d7Cc237EDFfBc57fBe2B319e10258A19e", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x3Da0f75d7Cc237EDFfBc57fBe2B319e10258A19e", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xC842D30Ef5e354cb2F6f15a7Da524f4A968C2911", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xC842D30Ef5e354cb2F6f15a7Da524f4A968C2911", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x2273eDFc040019BfA9198A8007F4880b4E18E4C0", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x2273eDFc040019BfA9198A8007F4880b4E18E4C0", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x4e1a3c4246faaefc2987cf19b5b0d958e4e42a0e", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x4e1a3c4246faaefc2987cf19b5b0d958e4e42a0e", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x5863e292fbdccb8bb3c8dd356c201a5e1524e419", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x5863e292fbdccb8bb3c8dd356c201a5e1524e419", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x1332a671a2437a33E07C08A99B067e8b2Ea7f4E2", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x1332a671a2437a33E07C08A99B067e8b2Ea7f4E2", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x6dffE761ee1b9Ec3a92deD9aA037DB85543Bb8de", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x6dffE761ee1b9Ec3a92deD9aA037DB85543Bb8de", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "cDe0c50fF41cDD3dd22457853D9C0b4c0C35dFE3", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "cDe0c50fF41cDD3dd22457853D9C0b4c0C35dFE3", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0B04675D9e11F9aD0280f7DE3E53bE01a90f8749", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0B04675D9e11F9aD0280f7DE3E53bE01a90f8749", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xB1dE485616f06cB6E244932cdEfe6c4678187684", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xB1dE485616f06cB6E244932cdEfe6c4678187684", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x5E55d7bf906f8b35adF4b73462C1a45030a2E5c9", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x5E55d7bf906f8b35adF4b73462C1a45030a2E5c9", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x0C8eDeffEfE778287978175Fdc9Eaa4c03f0Ed17", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x0C8eDeffEfE778287978175Fdc9Eaa4c03f0Ed17", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x20Ec8B699AE4BED7C31e72DA2cA638D3CaEed871", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x20Ec8B699AE4BED7C31e72DA2cA638D3CaEed871", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x42149d79bEEbb0C9d62f2436256f83707Afa09F7", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x42149d79bEEbb0C9d62f2436256f83707Afa09F7", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xe33E1E211bdF68147b72b91c176f90C7677AaF6B", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xe33E1E211bdF68147b72b91c176f90C7677AaF6B", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x5ACBbaC2C3130a347282dF5bB536b8E744B66A82", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x5ACBbaC2C3130a347282dF5bB536b8E744B66A82", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x3352daf507dc597ac47f227f7e27c71d684c3fde", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x3352daf507dc597ac47f227f7e27c71d684c3fde", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xd5c94Eba1431F8E481D1621402dABf204C1d12D3", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xd5c94Eba1431F8E481D1621402dABf204C1d12D3", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x15868524D44f60d9F2aC492A3A803a19d4E0AA5C", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x15868524D44f60d9F2aC492A3A803a19d4E0AA5C", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xCFed50e6F87605E9c834b75C22a666EFcD31566C", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xCFed50e6F87605E9c834b75C22a666EFcD31566C", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x000aAEE22EB8491e72fDff1fF3cDeB1cF071eE76", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x000aAEE22EB8491e72fDff1fF3cDeB1cF071eE76", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xF490274c5731B75F300560A5D4C0c40e28bD8669", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xF490274c5731B75F300560A5D4C0c40e28bD8669", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x24a8A579f2c1613780ea029e6Fc85b7d2b586c6b", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x24a8A579f2c1613780ea029e6Fc85b7d2b586c6b", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xA5b05c58054A3863DADb67950aBa007624DaAE1f", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 20002, - "revocable": false, - "beneficiary": "0xA5b05c58054A3863DADb67950aBa007624DaAE1f", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x7Ff03c3216573710a62831d5249D7A7CE4D017dE", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x7Ff03c3216573710a62831d5249D7A7CE4D017dE", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xCbBDa4307091f287a6C4BbE641D5C84014ed70d5", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 20002, - "revocable": false, - "beneficiary": "0xCbBDa4307091f287a6C4BbE641D5C84014ed70d5", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xc8269fb652e55d2ae6f379718d5ec5a49921607b", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xc8269fb652e55d2ae6f379718d5ec5a49921607b", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x44deceba63d392d8a178f566677021e8d2695765", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x44deceba63d392d8a178f566677021e8d2695765", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xfB32cab6De0BcC462917C8194DfC3A6C71e63d94", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xfB32cab6De0BcC462917C8194DfC3A6C71e63d94", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x39F641c7adeDB946d0670860E45CbcB9bEC4f4dA", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x39F641c7adeDB946d0670860E45CbcB9bEC4f4dA", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x23db1e5daa277d3b643ad9b44c8045ca21949bef", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x23db1e5daa277d3b643ad9b44c8045ca21949bef", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xd51247163529d327322712239e65c7e6aff0de82", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xd51247163529d327322712239e65c7e6aff0de82", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x4C7Cd95d47858D9B28C314D5b70149e2Ab1076C2", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x4C7Cd95d47858D9B28C314D5b70149e2Ab1076C2", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x88996e9484DB8f9398c8DFaC953585Bc7277eFE5", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 20002, - "revocable": false, - "beneficiary": "0x88996e9484DB8f9398c8DFaC953585Bc7277eFE5", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xa8AA9c53b6535656eb3dA9624105e6F4d5cb7bF4", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 20002, - "revocable": false, - "beneficiary": "0xa8AA9c53b6535656eb3dA9624105e6F4d5cb7bF4", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xd1687731C3661167706e53e4cfF43B37c8673189", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xd1687731C3661167706e53e4cfF43B37c8673189", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x93D3dC5eB8Bc021cF51ab4eD67050F094c5233f9", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x93D3dC5eB8Bc021cF51ab4eD67050F094c5233f9", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x0Dd1d9D813684bcbF127CCA52eCfa686fef1Db0a", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x0Dd1d9D813684bcbF127CCA52eCfa686fef1Db0a", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x580e765D0FF80d8a74Dd37b5a2E9FA4214A7D2Db", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x580e765D0FF80d8a74Dd37b5a2E9FA4214A7D2Db", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xBecc041a5090cD08AbD3940ab338d4CC94d2Ed3c", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xBecc041a5090cD08AbD3940ab338d4CC94d2Ed3c", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x231b10a19F5215BF218B7604114C0f2dF9Dc17a6", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 12502, - "revocable": false, - "beneficiary": "0x231b10a19F5215BF218B7604114C0f2dF9Dc17a6", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "Fb2D3069e3F36E04347174Cf01F6FBf43163DE6D", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "Fb2D3069e3F36E04347174Cf01F6FBf43163DE6D", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xAC271CC079A734C363f082A431b2270f56C49038", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10252, - "revocable": false, - "beneficiary": "0xAC271CC079A734C363f082A431b2270f56C49038", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "08cd011A0cE3F139d586c8a403Ea0b2610f1b5Ed", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "08cd011A0cE3F139d586c8a403Ea0b2610f1b5Ed", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "eDBd3d6E7077Ef2205230107259a851A78bb6Eb1", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 23302, - "revocable": false, - "beneficiary": "eDBd3d6E7077Ef2205230107259a851A78bb6Eb1", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x26994A9545C77EaE9E17A90E444eb228b8D192E4", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x26994A9545C77EaE9E17A90E444eb228b8D192E4", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x25C7731B5448D3002DCC0DFc256BC657e40deD33", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x25C7731B5448D3002DCC0DFc256BC657e40deD33", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x493881b5133f53f902c92c02C67EE35c0d50158D", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 30102, - "revocable": false, - "beneficiary": "0x493881b5133f53f902c92c02C67EE35c0d50158D", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x3d841f0b39e2daca569c09ade3ea3ca0e4359641", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x3d841f0b39e2daca569c09ade3ea3ca0e4359641", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x1d420010b8917fe71cb635abad88398a0e89b2a5", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x1d420010b8917fe71cb635abad88398a0e89b2a5", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x3D3E223B0f16e3D09f6B5b320422F52ad157bd1D", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x3D3E223B0f16e3D09f6B5b320422F52ad157bd1D", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x87f394e0deabb94d844ae62ff2aea730f75bd33d", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 11252, - "revocable": false, - "beneficiary": "0x87f394e0deabb94d844ae62ff2aea730f75bd33d", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x6eF5CB03FaaF615b0284a994386B930362217DE1", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x6eF5CB03FaaF615b0284a994386B930362217DE1", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x8072D7f3A3A6634cab850a83039223e22f20B04B", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x8072D7f3A3A6634cab850a83039223e22f20B04B", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x0F0CEAe30aD490B47e000449803F5e926D66dB0e", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x0F0CEAe30aD490B47e000449803F5e926D66dB0e", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xd19249cc30c84b068263Ba0e173FD19fAcD78f19", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 40902, - "revocable": false, - "beneficiary": "0xd19249cc30c84b068263Ba0e173FD19fAcD78f19", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x351aebcded9240ae77dd0a3987e2110b15e0f038", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 30002, - "revocable": false, - "beneficiary": "0x351aebcded9240ae77dd0a3987e2110b15e0f038", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x42ec39634217b708aa87befa85d6e87ddd335292", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x42ec39634217b708aa87befa85d6e87ddd335292", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x435b4b17f213b0cac1ebc17e3d08c800485866e9", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x435b4b17f213b0cac1ebc17e3d08c800485866e9", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xe4bece11dfb62a8a63569710302ef8bd70325e10", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xe4bece11dfb62a8a63569710302ef8bd70325e10", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xfec5e94e4a230b425ca6e19d82dbd8df7c65c680", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xfec5e94e4a230b425ca6e19d82dbd8df7c65c680", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "b6364907f4e5f7b3d35891144f9dbf9c571759d6", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 30002, - "revocable": false, - "beneficiary": "b6364907f4e5f7b3d35891144f9dbf9c571759d6", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "686d6f5215b79252a42b4a41ea5257009bec44a8", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "686d6f5215b79252a42b4a41ea5257009bec44a8", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "b056768bb484e29d90c09e330565ad8e1c24cc6a", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "b056768bb484e29d90c09e330565ad8e1c24cc6a", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x138976a2AE14ecC940F3D7E46C4a647c5dc2e3E8", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 33002, - "revocable": false, - "beneficiary": "0x138976a2AE14ecC940F3D7E46C4a647c5dc2e3E8", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x131cD6c660094B0967640E098E1280D6618c3742", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x131cD6c660094B0967640E098E1280D6618c3742", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xce2a38595a416e7f0f6eC9F86E4C5c3d28400C20", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xce2a38595a416e7f0f6eC9F86E4C5c3d28400C20", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x76A39Aa16276d30c137ae338EA99E2F3B8AC3CDA", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x76A39Aa16276d30c137ae338EA99E2F3B8AC3CDA", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xD38935223966BA19Ea73792b1dC92b71420B46fc", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xD38935223966BA19Ea73792b1dC92b71420B46fc", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x1C5fecC60f4F288e82354111681b2A466340bca8", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 20602, - "revocable": false, - "beneficiary": "0x1C5fecC60f4F288e82354111681b2A466340bca8", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0efcbf280ac18ef18884ac4624ada88fbfe43134", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0efcbf280ac18ef18884ac4624ada88fbfe43134", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "bb161c8a7128c20cee5e5e36038213e57d9bbc64", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 20002, - "revocable": false, - "beneficiary": "bb161c8a7128c20cee5e5e36038213e57d9bbc64", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xFD8cCe689A04E356AE13071C0c41Faf7552402Fb", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xFD8cCe689A04E356AE13071C0c41Faf7552402Fb", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xc2064926AFb167ffEcB8997235CAd1CCd5773228", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xc2064926AFb167ffEcB8997235CAd1CCd5773228", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xACd31B9a109c5227B165e4C9324723ae614cf903", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xACd31B9a109c5227B165e4C9324723ae614cf903", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x0627E5f7E0D1A3749764F8417133A77E7b2eE707", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x0627E5f7E0D1A3749764F8417133A77E7b2eE707", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x811fCDCA76977Aa7236f48dF1A37446fa13eC8cc", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 20002, - "revocable": false, - "beneficiary": "0x811fCDCA76977Aa7236f48dF1A37446fa13eC8cc", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x10e8a187b50fcda52adba67f98ff780aaba18104", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x10e8a187b50fcda52adba67f98ff780aaba18104", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x43d218fe26aab09ebf27b550f248d152d4ca9220", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x43d218fe26aab09ebf27b550f248d152d4ca9220", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xf02e1fB0Fe7F3962818Cf3a1301d766A511fF17F", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xf02e1fB0Fe7F3962818Cf3a1301d766A511fF17F", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x44EEcfc3eCa752254dBbc44ac037c7641f206d17", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 12102, - "revocable": false, - "beneficiary": "0x44EEcfc3eCa752254dBbc44ac037c7641f206d17", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x1a9e8e7f8a7b6400e5c70344842e38ff09e68131", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x1a9e8e7f8a7b6400e5c70344842e38ff09e68131", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x8b87de691f8bf0040ff585326eeb612de81f0d53", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x8b87de691f8bf0040ff585326eeb612de81f0d53", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xF215beB7F6d29aDba0aeFC2d2d1bE66748e1ACEe", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xF215beB7F6d29aDba0aeFC2d2d1bE66748e1ACEe", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x23265941b3248211f186034d2DD7aC25dCFBE8C7", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10202, - "revocable": false, - "beneficiary": "0x23265941b3248211f186034d2DD7aC25dCFBE8C7", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "64d8ba94b639a2c752dd6cb87ee641d2e6ce787e", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "64d8ba94b639a2c752dd6cb87ee641d2e6ce787e", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "80b2c7f9e297928764c493882a15b2f0292ad4d1", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "80b2c7f9e297928764c493882a15b2f0292ad4d1", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "7C99a549E5021aC25E756d81224f30b9ed086322", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "7C99a549E5021aC25E756d81224f30b9ed086322", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "2252fCdEa40B90cf0eD1b09C22914c7ffBb17Bf0", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "2252fCdEa40B90cf0eD1b09C22914c7ffBb17Bf0", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xD4A6dd7e815175fd5232dC32CF1c0dD926D81255", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xD4A6dd7e815175fd5232dC32CF1c0dD926D81255", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xD3ab7Ee9219EFA53298F7639fBEa54A3460F7240", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xD3ab7Ee9219EFA53298F7639fBEa54A3460F7240", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "36F669B1C347CB52Df8fa9e8FDE0b3061170669e", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "36F669B1C347CB52Df8fa9e8FDE0b3061170669e", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "4fC0e6c1AC6eD1c600e57baf304212dc8d98F7Fd", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "4fC0e6c1AC6eD1c600e57baf304212dc8d98F7Fd", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xC05153EaAEAb67D5BAc1C25B1e5675Fb85B75a08", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xC05153EaAEAb67D5BAc1C25B1e5675Fb85B75a08", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xf1014E08113bd8729D3D1657D883fe7EF4EA8897", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xf1014E08113bd8729D3D1657D883fe7EF4EA8897", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "658b5Df4E9deac0f3dabDe671CaEA3c77582f222", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "658b5Df4E9deac0f3dabDe671CaEA3c77582f222", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "FB5A0cf1baAeb160ef99E1Ac1a3794e5cCF20b9E", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "FB5A0cf1baAeb160ef99E1Ac1a3794e5cCF20b9E", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xeca46aFE86BD68FAcc70484Be8Bc2a826c63A2DC", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xeca46aFE86BD68FAcc70484Be8Bc2a826c63A2DC", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xFE917317e641774739AD4594536F67aD8e33c02F", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xFE917317e641774739AD4594536F67aD8e33c02F", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x3Ca536b532D00529d1B37f68137F011F2D1d2CeE", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x3Ca536b532D00529d1B37f68137F011F2D1d2CeE", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xC9298cBCe08d47323EDBfd2cf28eF26Dccbb21bA", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xC9298cBCe08d47323EDBfd2cf28eF26Dccbb21bA", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x111E7C6a17Ad27f45032C75BF6426958Dcbbc03A", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x111E7C6a17Ad27f45032C75BF6426958Dcbbc03A", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xF0eB19960A230129Ca5f6C25f3F5cfEb6887D099", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xF0eB19960A230129Ca5f6C25f3F5cfEb6887D099", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xB72c361EF13B3BCf7Fbf8209AE67AC298c75aA7C", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0xB72c361EF13B3BCf7Fbf8209AE67AC298c75aA7C", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x8267809F2f76D53f0a85486ccE9c2b8CBD8960aa", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x8267809F2f76D53f0a85486ccE9c2b8CBD8960aa", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x81a9cc4103e2c66a652b2c17baaf134fdaeafca9", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 11252, - "revocable": false, - "beneficiary": "0x81a9cc4103e2c66a652b2c17baaf134fdaeafca9", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x7F5bb79b6756afE35CC71b3850C829B5EC13e6d7", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x7F5bb79b6756afE35CC71b3850C829B5EC13e6d7", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0xf1cC0D8f2322AE86252Cf1D1F2308EE51BE336A6", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10202, - "revocable": false, - "beneficiary": "0xf1cC0D8f2322AE86252Cf1D1F2308EE51BE336A6", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x008105af3e4a32ce8476cb8927f482bc3830a714", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 31536000, - "numReleasePeriods": 1, - "releasePeriod": 31536000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x008105af3e4a32ce8476cb8927f482bc3830a714", - "releaseOwner": "0xf772F744f0152b6B85095a39f1d5541839710C6e", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - } -] \ No newline at end of file diff --git a/packages/celotool/tsconfig.json b/packages/celotool/tsconfig.json deleted file mode 100644 index 747699ef2..000000000 --- a/packages/celotool/tsconfig.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "extends": "@celo/typescript/tsconfig.library.json", - "compilerOptions": { - "outDir": "lib", - "rootDir": "src", - "baseUrl": ".", - "lib": ["es7", "es2017", "es2020"], - "target": "es2020", - "resolveJsonModule": true, - "esModuleInterop": true, - "paths": { - "@google-cloud/monitoring": ["types/monitoring"] - } - }, - "include": ["src"], - "exclude": ["node_modules/"], -} diff --git a/packages/celotool/tslint.json b/packages/celotool/tslint.json deleted file mode 100644 index ae0e82b60..000000000 --- a/packages/celotool/tslint.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "extends": ["@celo/typescript/tslint.json"], - "linterOptions": { - "exclude": ["**/__mocks__/**", "**/lcov-report/**"] - }, - "rules": { - "no-implicit-dependencies": [ - false, - [ - "src" - ] - ], - "no-relative-imports": false, - "max-classes-per-file": [true, 2], - "no-global-arrow-functions": false, - "no-floating-promises": true, - "no-bitwise": false - } -} diff --git a/packages/cli/package.json b/packages/cli/package.json index 79f083147..56fbad29e 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -73,12 +73,14 @@ "web3": "1.10.0" }, "devDependencies": { + "@celo/celo-devchain": "^6.0.3", - "@celo/dev-utils": "0.0.1", + "@celo/dev-utils": "0.0.1-beta.1", "@oclif/dev-cli": "^1.23.0", "@types/cli-table": "^0.3.0", "@types/debug": "^4.1.4", "@types/fs-extra": "^8.0.0", + "@types/prompts": "^1.1.1", "@types/humanize-duration": "^3.27.0", "@types/inquirer": "^6.5.0", "@types/ledgerhq__hw-transport-node-hid": "^4.22.2", diff --git a/packages/dev-utils/.gitignore b/packages/dev-utils/.gitignore deleted file mode 100644 index 7951405f8..000000000 --- a/packages/dev-utils/.gitignore +++ /dev/null @@ -1 +0,0 @@ -lib \ No newline at end of file diff --git a/packages/dev-utils/README.md b/packages/dev-utils/README.md deleted file mode 100644 index e61ba036a..000000000 --- a/packages/dev-utils/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# packages/dev-utils - -This is a `utils` package that is meant to be used as a devDependency. It's primary use case is to reuse the ganache setup currently present in `cli` and `contractkit`. Due to the way jest uses globalSetup, depending packages will still need to define their own setup/teardown files. diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json deleted file mode 100644 index 37afef8c0..000000000 --- a/packages/dev-utils/package.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "@celo/dev-utils", - "version": "0.0.1", - "private": false, - "description": "util package for celo packages that should only be a devDependency", - "main": "./lib/index.js", - "types": "./lib/index.d.ts", - "author": "Celo", - "license": "Apache-2.0", - "homepage": "https://github.com/celo-org/celo-monorepo/tree/master/packages/dev-utils", - "repository": "https://github.com/celo-org/celo-monorepo/tree/master/packages/dev-utils", - "keywords": [ - "celo" - ], - "scripts": { - "build": "tsc -b .", - "lint": "tslint -c tslint.json --project ." - }, - "dependencies": { - "ganache": "npm:@celo/ganache@7.8.0-unofficial.0", - "bignumber.js": "^9.0.0", - "web3": "1.10.0", - "web3-core-helpers": "1.10.0", - "tmp": "^0.1.0", - "targz": "^1.0.1", - "fs-extra": "^8.1.0" - }, - "devDependencies": { - "@types/fs-extra": "^8.1.0", - "@types/targz": "1.0.0" - }, - "engines": { - "node": ">=8.14.2" - } -} \ No newline at end of file diff --git a/packages/dev-utils/src/describeEach.ts b/packages/dev-utils/src/describeEach.ts deleted file mode 100644 index 301ce4d18..000000000 --- a/packages/dev-utils/src/describeEach.ts +++ /dev/null @@ -1,9 +0,0 @@ -export interface TestCase { - label: string -} - -export function describeEach(testCases: T[], fn: (testCase: T) => void) { - for (const testCase of testCases) { - describe(testCase.label, () => fn(testCase)) - } -} diff --git a/packages/dev-utils/src/ganache-setup.ts b/packages/dev-utils/src/ganache-setup.ts deleted file mode 100644 index dd9746628..000000000 --- a/packages/dev-utils/src/ganache-setup.ts +++ /dev/null @@ -1,132 +0,0 @@ -import * as fs from 'fs-extra' -// @ts-ignore -import * as ganache from 'ganache' -import * as path from 'path' -import * as targz from 'targz' - -const MNEMONIC = 'concert load couple harbor equip island argue ramp clarify fence smart topic' -export const ACCOUNT_PRIVATE_KEYS = [ - '0xf2f48ee19680706196e2e339e5da3491186e0c4c5030670656b0e0164837257d', - '0x5d862464fe9303452126c8bc94274b8c5f9874cbd219789b3eb2128075a76f72', - '0xdf02719c4df8b9b8ac7f551fcb5d9ef48fa27eef7a66453879f4d8fdc6e78fb1', - '0xff12e391b79415e941a94de3bf3a9aee577aed0731e297d5cfa0b8a1e02fa1d0', - '0x752dd9cf65e68cfaba7d60225cbdbc1f4729dd5e5507def72815ed0d8abc6249', - '0xefb595a0178eb79a8df953f87c5148402a224cdf725e88c0146727c6aceadccd', - '0x83c6d2cc5ddcf9711a6d59b417dc20eb48afd58d45290099e5987e3d768f328f', - '0xbb2d3f7c9583780a7d3904a2f55d792707c345f21de1bacb2d389934d82796b2', - '0xb2fd4d29c1390b71b8795ae81196bfd60293adf99f9d32a0aff06288fcdac55f', - '0x23cb7121166b9a2f93ae0b7c05bde02eae50d64449b2cbb42bc84e9d38d6cc89', -] -export const ACCOUNT_ADDRESSES = [ - '0x5409ED021D9299bf6814279A6A1411A7e866A631', - '0x6Ecbe1DB9EF729CBe972C83Fb886247691Fb6beb', - '0xE36Ea790bc9d7AB70C55260C66D52b1eca985f84', - '0xE834EC434DABA538cd1b9Fe1582052B880BD7e63', - '0x78dc5D2D739606d31509C31d654056A45185ECb6', - '0xA8dDa8d7F5310E4A9E24F8eBA77E091Ac264f872', - '0x06cEf8E666768cC40Cc78CF93d9611019dDcB628', - '0x4404ac8bd8F9618D27Ad2f1485AA1B2cFD82482D', - '0x7457d5E02197480Db681D3fdF256c7acA21bDc12', - '0x91c987bf62D25945dB517BDAa840A6c661374402', -] - -export async function startGanache( - filePath: string, - datafile: string, - opts: { verbose?: boolean; from_targz?: boolean } = {} -) { - const chainCopyBase = process.env.GANACHE_CHAIN_DATA_PATH || path.resolve(filePath) - const chainCopy: string = path.resolve(path.join(chainCopyBase, 'tmp/copychain')) - console.log(chainCopy) - console.log(filePath, datafile) - const filenameWithPath: string = path.resolve(path.join(filePath, datafile)) - - // erases tmp chain - if (fs.existsSync(chainCopy)) { - console.log(`Removing old chain tmp folder: ${chainCopy}`) - fs.removeSync(chainCopy) - } - console.log(`Creating chain tmp folder: ${chainCopy}`) - fs.mkdirsSync(chainCopy) - - if (opts.from_targz) { - await decompressChain(filenameWithPath, chainCopy) - } else { - fs.copySync(filenameWithPath, chainCopy) - } - - return launchServer(opts, chainCopy) -} - -async function launchServer(opts: { verbose?: boolean; from_targz?: boolean }, chain?: string) { - const logFn = opts.verbose - ? // tslint:disable-next-line: no-console - (...args: any[]) => console.log(...args) - : () => { - /*nothing*/ - } - - const server = ganache.server({ - wallet: { mnemonic: MNEMONIC, defaultBalance: 1000000 }, - logging: { logger: { log: logFn } }, - database: { dbPath: chain }, - miner: { blockGasLimit: 20000000, defaultGasPrice: 0 }, - chain: { networkId: 1101, chainId: 1, allowUnlimitedContractSize: true, hardfork: 'istanbul' }, - }) - - server.listen(8545, async (err: any) => { - if (err) { - throw err - } - }) - - return async () => { - try { - await server.close() - } catch (e) { - throw e - } - } -} - -function decompressChain(tarPath: string, copyChainPath: string): Promise { - console.log('Decompressing chain') - return new Promise((resolve, reject) => { - targz.decompress({ src: tarPath, dest: copyChainPath }, (err) => { - if (err) { - console.error(err) - reject(err) - } else { - console.log('Chain decompressed') - resolve() - } - }) - }) -} - -export default function setup( - filePath: string, - datafile: string, - opts: { verbose?: boolean; from_targz?: boolean } = {} -) { - return startGanache(filePath, datafile, opts) - .then((stopGanache) => { - ;(global as any).stopGanache = stopGanache - }) - .catch((err) => { - console.error('Error starting ganache') - console.error(err) - process.exit(1) - }) -} - -export function emptySetup(opts: { verbose?: boolean; from_targz?: boolean } = {}) { - return launchServer(opts) - .then((stopGanache) => { - ;(global as any).stopGanache = stopGanache - }) - .catch((err) => { - console.error(err) - process.exit(1) - }) -} diff --git a/packages/dev-utils/src/ganache-teardown.ts b/packages/dev-utils/src/ganache-teardown.ts deleted file mode 100644 index 27400b9a1..000000000 --- a/packages/dev-utils/src/ganache-teardown.ts +++ /dev/null @@ -1,7 +0,0 @@ -export default function tearDown() { - console.log('Stopping ganache') - return (global as any).stopGanache().catch((err: any) => { - console.error('error stopping ganache') - console.error(err) - }) -} diff --git a/packages/dev-utils/src/ganache-test.ts b/packages/dev-utils/src/ganache-test.ts deleted file mode 100644 index 2722d043f..000000000 --- a/packages/dev-utils/src/ganache-test.ts +++ /dev/null @@ -1,113 +0,0 @@ -import Web3 from 'web3' -import { JsonRpcResponse } from 'web3-core-helpers' -import migrationOverride from './migration-override.json' - -export const NetworkConfig = migrationOverride - -export function jsonRpcCall(web3: Web3, method: string, params: any[]): Promise { - return new Promise((resolve, reject) => { - if (web3.currentProvider && typeof web3.currentProvider !== 'string') { - web3.currentProvider.send!( - { - id: new Date().getTime(), - jsonrpc: '2.0', - method, - params, - }, - (err: Error | null, res?: JsonRpcResponse) => { - if (err) { - reject(err) - } else if (!res) { - reject(new Error('no response')) - } else if (res.error) { - reject( - new Error( - `Failed JsonRpcResponse: method: ${method} params: ${params} error: ${JSON.stringify( - res.error - )}` - ) - ) - } else { - resolve(res.result) - } - } - ) - } else { - reject(new Error('Invalid provider')) - } - }) -} - -export async function timeTravel(seconds: number, web3: Web3) { - await jsonRpcCall(web3, 'evm_increaseTime', [seconds]) - await jsonRpcCall(web3, 'evm_mine', []) -} - -export async function mineBlocks(blocks: number, web3: Web3) { - for (let i = 0; i < blocks; i++) { - await jsonRpcCall(web3, 'evm_mine', []) - } -} - -export function evmRevert(web3: Web3, snapId: string): Promise { - return jsonRpcCall(web3, 'evm_revert', [snapId]) -} - -export function evmSnapshot(web3: Web3) { - return jsonRpcCall(web3, 'evm_snapshot', []) -} - -export function testWithGanache(name: string, fn: (web3: Web3) => void) { - const web3 = new Web3('http://localhost:8545') - - describe(name, () => { - let snapId: string | null = null - - beforeEach(async () => { - if (snapId != null) { - await evmRevert(web3, snapId) - } - snapId = await evmSnapshot(web3) - }) - - afterAll(async () => { - if (snapId != null) { - await evmRevert(web3, snapId) - } - }) - - fn(web3) - }) -} - -/** - * Gets a contract address by parsing blocks and matching event signatures against the given event. - */ -export async function getContractFromEvent( - eventSignature: string, - web3: Web3, - filter?: { - expectedData?: string - index?: number - } -): Promise { - const logs = await web3.eth.getPastLogs({ - topics: [web3.utils.sha3(eventSignature)], - fromBlock: 'earliest', - toBlock: 'latest', - }) - if (logs.length === 0) { - throw Error(`Error: contract could not be found matching signature ${eventSignature}`) - } - const logIndex = filter?.index ?? 0 - if (!filter?.expectedData) { - return logs[logIndex].address - } - const filteredLogs = logs.filter((log) => log.data === filter.expectedData) - if (filteredLogs.length === 0) { - throw Error( - `Error: contract could not be found matching signature ${eventSignature} with data ${filter.expectedData}` - ) - } - return filteredLogs[logIndex ?? 0].address -} diff --git a/packages/dev-utils/src/matchers.ts b/packages/dev-utils/src/matchers.ts deleted file mode 100644 index c0bac376f..000000000 --- a/packages/dev-utils/src/matchers.ts +++ /dev/null @@ -1,43 +0,0 @@ -import BigNumber from 'bignumber.js' - -declare global { - namespace jest { - interface Matchers { - toBeBigNumber(): R - toEqBigNumber(expected: BigNumber | string | number): R - } - } -} -jest.setTimeout(10000) - -expect.extend({ - toBeBigNumber(received: any) { - const pass = BigNumber.isBigNumber(received) - if (pass) { - return { - message: () => `expected ${received} not to be BigNumber`, - pass: true, - } - } else { - return { - message: () => `expected ${received} to be bigNumber`, - pass: false, - } - } - }, - toEqBigNumber(received: BigNumber, _expected: BigNumber | string | number) { - const expected = new BigNumber(_expected) - const pass = expected.eq(received) - if (pass) { - return { - message: () => `expected ${received.toString()} not to equal ${expected.toString()}`, - pass: true, - } - } else { - return { - message: () => `expected ${received.toString()} to equal ${expected.toString()}`, - pass: false, - } - } - }, -}) diff --git a/packages/dev-utils/src/migration-override.json b/packages/dev-utils/src/migration-override.json deleted file mode 100644 index 213756a69..000000000 --- a/packages/dev-utils/src/migration-override.json +++ /dev/null @@ -1,127 +0,0 @@ -{ - "downtimeSlasher": { - "slashableDowntime": 60 - }, - "epochRewards": { - "frozen": false - }, - "exchange": { - "frozen": false, - "minimumReports": 1 - }, - "exchangeEUR": { - "frozen": false, - "minimumReports": 1 - }, - "goldToken": { - "frozen": false - }, - "governance": { - "dequeueFrequency": 30, - "queueExpiry": 1000, - "approvalStageDuration": 100, - "referendumStageDuration": 100, - "executionStageDuration": 100, - "minDeposit": 1, - "concurrentProposals": 5, - "skipTransferOwnership": false - }, - "governanceApproverMultiSig": { - "signatories": [ - "0x5409ed021d9299bf6814279a6a1411a7e866a631" - ], - "numRequiredConfirmations": 1 - }, - "grandaMento": { - "approver": "0x5409ED021D9299bf6814279A6A1411A7e866A631", - "spread": 0.01, - "maxApprovalExchangeRateChange": 0.5, - "vetoPeriodSeconds": 10800 - }, - "oracles": { - "reportExpiry": 300 - }, - "reserve": { - "initialBalance": 100000000, - "otherAddresses": ["0x91c987bf62D25945dB517BDAa840A6c661374402"] - }, - "reserveSpenderMultiSig": { - "signatories": ["0x5409ed021d9299bf6814279a6a1411a7e866a631", "0x4404ac8bd8F9618D27Ad2f1485AA1B2cFD82482D"], - "numRequiredConfirmations": 2 - }, - "stableToken": { - "goldPrice": 1, - "initialBalances": { - "addresses": [ - "0x5409ED021D9299bf6814279A6A1411A7e866A631", - "0x6Ecbe1DB9EF729CBe972C83Fb886247691Fb6beb", - "0xE36Ea790bc9d7AB70C55260C66D52b1eca985f84", - "0xE834EC434DABA538cd1b9Fe1582052B880BD7e63" - ], - "values": [ - "50000000000000000000000", - "50000000000000000000000", - "50000000000000000000000", - "50000000000000000000000" - ] - }, - "oracles": [ - "0x5409ED021D9299bf6814279A6A1411A7e866A631", - "0xE36Ea790bc9d7AB70C55260C66D52b1eca985f84", - "0x06cEf8E666768cC40Cc78CF93d9611019dDcB628", - "0x7457d5E02197480Db681D3fdF256c7acA21bDc12" - ], - "frozen": false - }, - "stableTokenEUR": { - "goldPrice": 1, - "initialBalances": { - "addresses": [ - "0x5409ED021D9299bf6814279A6A1411A7e866A631", - "0x6Ecbe1DB9EF729CBe972C83Fb886247691Fb6beb", - "0xE36Ea790bc9d7AB70C55260C66D52b1eca985f84", - "0xE834EC434DABA538cd1b9Fe1582052B880BD7e63" - ], - "values": [ - "50000000000000000000000", - "50000000000000000000000", - "50000000000000000000000", - "50000000000000000000000" - ] - }, - "oracles": [ - "0x5409ED021D9299bf6814279A6A1411A7e866A631", - "0xE36Ea790bc9d7AB70C55260C66D52b1eca985f84", - "0x06cEf8E666768cC40Cc78CF93d9611019dDcB628", - "0x7457d5E02197480Db681D3fdF256c7acA21bDc12" - ], - "frozen": false - }, - "stableTokenBRL": { - "goldPrice": 1, - "initialBalances": { - "addresses": [ - "0x5409ED021D9299bf6814279A6A1411A7e866A631", - "0x6Ecbe1DB9EF729CBe972C83Fb886247691Fb6beb", - "0xE36Ea790bc9d7AB70C55260C66D52b1eca985f84", - "0xE834EC434DABA538cd1b9Fe1582052B880BD7e63" - ], - "values": [ - "50000000000000000000000", - "50000000000000000000000", - "50000000000000000000000", - "50000000000000000000000" - ] - }, - "oracles": [ - "0x5409ED021D9299bf6814279A6A1411A7e866A631", - "0xE36Ea790bc9d7AB70C55260C66D52b1eca985f84", - "0x06cEf8E666768cC40Cc78CF93d9611019dDcB628", - "0x7457d5E02197480Db681D3fdF256c7acA21bDc12" - ], - "frozen": false - }, - "validators": { - "commissionUpdateDelay": 3 - } -} diff --git a/packages/dev-utils/src/network.ts b/packages/dev-utils/src/network.ts deleted file mode 100644 index 8801372e8..000000000 --- a/packages/dev-utils/src/network.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { spawn, SpawnOptions } from 'child_process' - -export async function waitForPortOpen(host: string, port: number, seconds: number) { - const deadline = Date.now() + seconds * 1000 - do { - if (await isPortOpen(host, port)) { - return true - } - } while (Date.now() < deadline) - return false -} - -export async function isPortOpen(host: string, port: number) { - return (await execCmd('nc', ['-z', host, port.toString()], { silent: true })) === 0 -} - -function execCmd(cmd: string, args: string[], options?: SpawnOptions & { silent?: boolean }) { - return new Promise(async (resolve, reject) => { - const { silent, ...spawnOptions } = options || { silent: false } - if (!silent) { - console.debug('$ ' + [cmd].concat(args).join(' ')) - } - const process = spawn(cmd, args, { ...spawnOptions, stdio: silent ? 'ignore' : 'inherit' }) - process.on('close', (code) => { - try { - resolve(code as number) - } catch (error) { - reject(error) - } - }) - }) -} diff --git a/packages/dev-utils/tsconfig.json b/packages/dev-utils/tsconfig.json deleted file mode 100644 index f08034922..000000000 --- a/packages/dev-utils/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "@celo/typescript/tsconfig.library.json", - "compilerOptions": { - "rootDir": "src", - "outDir": "lib", - "resolveJsonModule": true - }, - "include": ["src", "types/", "src/migration-override.json"] -} diff --git a/packages/dev-utils/tslint.json b/packages/dev-utils/tslint.json deleted file mode 100644 index 036f00068..000000000 --- a/packages/dev-utils/tslint.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": ["@celo/typescript/tslint.json"], - "rules": { - "no-global-arrow-functions": false, - "no-console": false, - "member-ordering": false, - "max-classes-per-file": false - } -} diff --git a/packages/env-tests/.gitignore b/packages/env-tests/.gitignore deleted file mode 100644 index 592a8d4a3..000000000 --- a/packages/env-tests/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.js -!jest.config.js -lib \ No newline at end of file diff --git a/packages/env-tests/CHANGELOG.md b/packages/env-tests/CHANGELOG.md deleted file mode 100644 index 89bd1d22d..000000000 --- a/packages/env-tests/CHANGELOG.md +++ /dev/null @@ -1,87 +0,0 @@ -# @celo/env-tests - -## 1.0.3 - -### Patch Changes - -- Updated dependencies [9ab9d00eb] -- Updated dependencies [1c9c844cf] -- Updated dependencies [9ab9d00eb] - - @celo/contractkit@6.0.0 - -## 1.0.3-beta.0 - -### Patch Changes - -- Updated dependencies [1c9c844cf] - - @celo/contractkit@6.0.0-beta.0 - - -## 1.0.2 - -### Patch Changes - -- 22ea7f691: Remove moment.js dependency -- Updated dependencies -- Updated dependencies [679ef0c60] -- Updated dependencies [97d5ccf43] -- Updated dependencies [32face3d8] -- Updated dependencies [97d5ccf43] -- Updated dependencies [87647b46b] - - @celo/contractkit@5.2.0 - - @celo/connect@5.1.1 - - @celo/phone-utils@6.0.0 - - @celo/base@6.0.0 - - @celo/cryptographic-utils@5.0.6 - - @celo/utils@5.0.6 - -## 1.0.2-beta.0 - -### Patch Changes - -- 22ea7f691: Remove moment.js dependency -- Updated dependencies -- Updated dependencies [97d5ccf43] -- Updated dependencies [32face3d8] -- Updated dependencies [97d5ccf43] -- Updated dependencies [87647b46b] - - @celo/contractkit@5.2.0-beta.0 - - @celo/phone-utils@6.0.0-beta.0 - - @celo/base@6.0.0-beta.0 - - @celo/connect@5.1.1-beta.0 - - @celo/cryptographic-utils@5.0.6-beta.0 - - @celo/utils@5.0.6-beta.0 - -## 1.0.1 - -### Patch Changes - -- Updated dependencies [d48c68afc] -- Updated dependencies [d48c68afc] -- Updated dependencies [53bbd4958] -- Updated dependencies [d48c68afc] -- Updated dependencies [53bbd4958] -- Updated dependencies [d48c68afc] - - @celo/contractkit@5.1.0 - - @celo/connect@5.1.0 - - @celo/cryptographic-utils@5.0.5 - - @celo/phone-utils@5.0.5 - - @celo/utils@5.0.5 - - @celo/base@5.0.5 - -## 1.0.1-beta.0 - -### Patch Changes - -- Updated dependencies [d48c68afc] -- Updated dependencies [d48c68afc] -- Updated dependencies [53bbd4958] -- Updated dependencies [d48c68afc] -- Updated dependencies [53bbd4958] -- Updated dependencies [d48c68afc] - - @celo/contractkit@5.1.0-beta.0 - - @celo/connect@5.1.0-beta.0 - - @celo/cryptographic-utils@5.0.5-beta.0 - - @celo/phone-utils@5.0.5-beta.0 - - @celo/utils@5.0.5-beta.0 - - @celo/base@5.0.5-beta.0 diff --git a/packages/env-tests/README.md b/packages/env-tests/README.md deleted file mode 100644 index 620e7f177..000000000 --- a/packages/env-tests/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# Env-tests - -The `env-tests` package is a set of tests that is designed to be run against CELO blockchains and assert that various platform interactions work as intended. It currently has tests for the following: - -1. Exchange: Does an exchange on Mento -2. Oracle: Reports an exchange rate -3. Reserve: Tests that reserve spenders can move funds to reserve custodians -4. Transfer: Does simple ERC20 transfers - -## Setup - -`env-tests` work by deriving keys from a single mnemonic. When run in the context of the monorepo, it will pull the relevant environment mnemonic, otherwise it should be passed to the `context` of the test setup. - -All keys derive funds from the "root key" which should be funded. From it, all test keys are funded in the test setup, increase verbosity with the `LOG_LEVEL` env var to `info` or `debug` to see more information. - -By default, transfer and exchange tests are performed for cUSD. By setting the env variable `STABLETOKENS` other stabletokens can be included in testing. `STABLETOKENS` can be set to a comma-separated string of stabletokens to test (e.g. `‘cEUR’` for only testing cEUR or `‘cUSD,cEUR’` for testing both cUSD and cEUR). - -As part of the testnet contract deploys in `celotool`, privileged keys like reserve spender or oracles can be authorized directly in the migrations. Hence, the relevant tests will pass on environments like `staging` while failing on public environments as the keys are not yet authorized. - -## Running the test - -Since all the keys are derived from a single mnemonic, the `env-tests` just need a node for chain interactions and not key management. Theoretically, running against forno would work and the embedded `yarn` commands set that up. However, since Forno currently does not have sticky sessions everywhere, tests can appear flaky. Instead, consider using a local lightest client or port-forwarding with `celotool port-forward -e ${ENVIRONMENT_NAME}`. diff --git a/packages/env-tests/index.d.ts b/packages/env-tests/index.d.ts deleted file mode 100644 index 102dc17cf..000000000 --- a/packages/env-tests/index.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module 'bunyan-debug-stream' diff --git a/packages/env-tests/jest.config.js b/packages/env-tests/jest.config.js deleted file mode 100644 index 54dfe8710..000000000 --- a/packages/env-tests/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - preset: 'ts-jest', - testMatch: ['/src/**/?(*.)+(spec|test).ts?(x)', '/src/monorepoRun.ts'], - verbose: true, -} diff --git a/packages/env-tests/package.json b/packages/env-tests/package.json deleted file mode 100644 index 771ca3194..000000000 --- a/packages/env-tests/package.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "@celo/env-tests", - "private": true, - "version": "1.0.3", - "description": "Environment tests", - "main": "index.js", - "license": "MIT", - "dependencies": { - "@celo/contractkit": "^6.0.0", - "@celo/utils": "^5.0.6", - "@celo/base": "^6.0.0", - "@celo/connect": "^5.1.1", - "@celo/phone-utils": "^6.0.0", - "@celo/cryptographic-utils": "^5.0.6", - "bignumber.js": "^9.0.0", - "bunyan": "1.8.12", - "bunyan-gke-stackdriver": "0.1.2", - "bunyan-debug-stream": "2.0.0", - "dotenv": "8.2.0", - "jest": "^29.0.2", - "web3": "1.10.0" - }, - "scripts": { - "clean": "tsc -b . --clean", - "build": "tsc -b .", - "lint": "tslint -c tslint.json --project tsconfig.json", - "test": "jest --runInBand", - "baklava-test": "CELO_ENV=baklava CELO_PROVIDER=https://baklava-forno.celo-testnet.org jest --runInBand", - "alfajores-test": "CELO_ENV=alfajores CELO_PROVIDER=https://alfajores-forno.celo-testnet.org jest --runInBand", - "mainnet-test": "CELO_ENV=rc1 CELO_PROVIDER=https://forno.celo.org jest --runInBand", - "staging-test": "CELO_ENV=staging CELO_PROVIDER=https://staging-forno.celo-networks-dev.org jest --runInBand" - }, - "devDependencies": { - "@jest/globals": "^29.5.0", - "typescript": "4.4.3" - } -} \ No newline at end of file diff --git a/packages/env-tests/src/context.ts b/packages/env-tests/src/context.ts deleted file mode 100644 index 07db35fec..000000000 --- a/packages/env-tests/src/context.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Address, ContractKit } from '@celo/contractkit' -import Logger from 'bunyan' - -export interface EnvTestContext { - kit: ContractKit - mnemonic: string - reserveSpenderMultiSigAddress: Address | undefined - logger: Logger -} diff --git a/packages/env-tests/src/env.ts b/packages/env-tests/src/env.ts deleted file mode 100644 index 948effaa2..000000000 --- a/packages/env-tests/src/env.ts +++ /dev/null @@ -1,63 +0,0 @@ -import * as dotenv from 'dotenv' -import { existsSync } from 'fs' -import path from 'path' - -if (process.env.CONFIG) { - dotenv.config({ path: process.env.CONFIG }) -} - -export function fetchEnv(name: string): string { - if (process.env[name] === undefined || process.env[name] === '') { - console.error(`ENV var '${name}' was not defined`) - throw new Error(`ENV var '${name}' was not defined`) - } - return process.env[name] as string -} - -export function fetchEnvOrDefault(name: string, defaultValue: string): string { - return process.env[name] === undefined || process.env[name] === '' - ? defaultValue - : (process.env[name] as string) -} - -export function isYes(value: string) { - switch (value.toLowerCase().trim()) { - case '1': - case 'y': - case 'yes': - case 't': - case 'true': - return true - default: - return false - } -} - -// Only use this if in monorepo and env files are as expected and in dev -export function loadFromEnvFile() { - const envName = process.env.CELO_ENV - - if (!envName) { - return - } - - const envFile = getEnvFile(envName) - dotenv.config({ path: envFile }) - - const envFileMnemonic = getEnvFile(envName, '.mnemonic') - dotenv.config({ path: envFileMnemonic }) - - return envName -} - -export const monorepoRoot = path.resolve(process.cwd(), './../..') -export const genericEnvFilePath = path.resolve(monorepoRoot, '.env') - -export function getEnvFile(celoEnv: string, envBegining: string = '') { - const filePath: string = path.resolve(monorepoRoot, `.env${envBegining}.${celoEnv}`) - if (existsSync(filePath)) { - return filePath - } else { - return `${genericEnvFilePath}${envBegining}` - } -} diff --git a/packages/env-tests/src/logger.ts b/packages/env-tests/src/logger.ts deleted file mode 100644 index 5bfd683e0..000000000 --- a/packages/env-tests/src/logger.ts +++ /dev/null @@ -1,26 +0,0 @@ -import Logger, { createLogger, levelFromName, LogLevelString, stdSerializers } from 'bunyan' -import bunyanDebugStream from 'bunyan-debug-stream' -import { createStream } from 'bunyan-gke-stackdriver' -import { fetchEnvOrDefault } from './env' - -const logLevel = fetchEnvOrDefault('LOG_LEVEL', 'info') as LogLevelString -const logFormat = fetchEnvOrDefault('LOG_FORMAT', 'human') - -let stream: any -switch (logFormat) { - case 'stackdriver': - stream = createStream(levelFromName[logLevel]) - break - case 'json': - stream = { stream: process.stdout, level: logLevel } - break - default: - stream = { level: logLevel, stream: bunyanDebugStream() } - break -} - -export const rootLogger: Logger = createLogger({ - name: 'env-tests', - serializers: stdSerializers, - streams: [stream], -}) diff --git a/packages/env-tests/src/monorepoRun.ts b/packages/env-tests/src/monorepoRun.ts deleted file mode 100644 index 4cb689f5a..000000000 --- a/packages/env-tests/src/monorepoRun.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { newKitFromWeb3, StableToken } from '@celo/contractkit' -import Web3 from 'web3' -import { loadFromEnvFile } from './env' -import { rootLogger } from './logger' -import { clearAllFundsToRoot, parseStableTokensList } from './scaffold' -import { runExchangeTest } from './tests/exchange' -import { runGrandaMentoTest } from './tests/granda-mento' -import { runOracleTest } from './tests/oracle' -import { runReserveTest } from './tests/reserve' -import { runTransfersTest } from './tests/transfer' - -const DEFAULT_TOKENS_TO_TEST = [StableToken.cUSD] - -jest.setTimeout(120000) - -function runTests() { - const envName = loadFromEnvFile() - - if (!process.env.MNEMONIC) { - throw new Error('No MNEMONIC was set, envName was parsed as ' + envName) - } - const kit = newKitFromWeb3(new Web3(process.env.CELO_PROVIDER || 'http://localhost:8545')) - const mnemonic = process.env.MNEMONIC! - const reserveSpenderMultiSigAddress = process.env.RESERVE_SPENDER_MULTISIG_ADDRESS - - const stableTokensToTest = process.env.STABLETOKENS - ? parseStableTokensList(process.env.STABLETOKENS) - : DEFAULT_TOKENS_TO_TEST - - describe('Run tests in context of monorepo', () => { - const context = { - kit, - mnemonic, - logger: rootLogger, - reserveSpenderMultiSigAddress, - } - - // TODO: Assert maximum loss after test - runTransfersTest(context, stableTokensToTest) - runExchangeTest(context, stableTokensToTest) - runOracleTest(context) - runReserveTest(context) - runGrandaMentoTest(context, stableTokensToTest) - - // TODO: Governance Proposals - // TODO: Validator election + Slashing - - afterAll(async () => { - await clearAllFundsToRoot(context, stableTokensToTest) - }) - }) -} - -runTests() diff --git a/packages/env-tests/src/scaffold.ts b/packages/env-tests/src/scaffold.ts deleted file mode 100644 index 00fd07bea..000000000 --- a/packages/env-tests/src/scaffold.ts +++ /dev/null @@ -1,186 +0,0 @@ -import { concurrentMap } from '@celo/base' -import { CeloTokenType, StableToken, Token } from '@celo/contractkit' -import { generateKeys } from '@celo/cryptographic-utils/lib/account' -import { privateKeyToAddress } from '@celo/utils/lib/address' -import BigNumber from 'bignumber.js' -import { EnvTestContext } from './context' - -BigNumber.config({ EXPONENTIAL_AT: 1e9 }) - -interface KeyInfo { - address: string - privateKey: string - publicKey: string -} - -export async function fundAccountWithCELO( - context: EnvTestContext, - account: TestAccounts, - value: BigNumber -) { - return fundAccount(context, account, value, Token.CELO) -} - -export async function fundAccountWithcUSD( - context: EnvTestContext, - account: TestAccounts, - value: BigNumber -) { - await fundAccountWithStableToken(context, account, value, StableToken.cUSD) -} - -export async function fundAccountWithStableToken( - context: EnvTestContext, - account: TestAccounts, - value: BigNumber, - stableToken: StableToken -) { - return fundAccount(context, account, value, stableToken) -} - -async function fundAccount( - context: EnvTestContext, - account: TestAccounts, - value: BigNumber, - token: CeloTokenType -) { - const tokenWrapper = await context.kit.celoTokens.getWrapper(token) - - const root = await getKey(context.mnemonic, TestAccounts.Root) - context.kit.connection.addAccount(root.privateKey) - - const recipient = await getKey(context.mnemonic, account) - const logger = context.logger.child({ - token, - index: account, - root: root.address, - value: value.toString(), - recipient: recipient.address, - }) - - const rootBalance = await tokenWrapper.balanceOf(root.address) - if (rootBalance.lte(value)) { - logger.error({ rootBalance: rootBalance.toString() }, 'Error funding test account') - throw new Error( - `Root account ${root.address}'s ${token} balance (${rootBalance.toPrecision( - 4 - )}) is not enough for transferring ${value.toPrecision(4)}` - ) - } - const receipt = await tokenWrapper - .transfer(recipient.address, value.toString()) - .sendAndWaitForReceipt({ - from: root.address, - feeCurrency: token === Token.CELO ? undefined : tokenWrapper.address, - }) - logger.info({ rootFundingReceipt: receipt, value }, `Root funded recipient`) -} - -export async function getValidatorKey(mnemonic: string, index: number): Promise { - return getKey(mnemonic, index, '') -} - -export async function getKey( - mnemonic: string, - account: TestAccounts, - derivationPath?: string -): Promise { - const key = await generateKeys(mnemonic, undefined, 0, account, undefined, derivationPath) - return { ...key, address: privateKeyToAddress(key.privateKey) } -} - -export enum TestAccounts { - Root, - GrandaMentoExchanger, - TransferFrom, - TransferTo, - Exchange, - Oracle, - GovernanceApprover, - ReserveSpender, - ReserveCustodian, -} - -export const ONE = new BigNumber('1000000000000000000') - -export async function clearAllFundsToRoot( - context: EnvTestContext, - stableTokensToClear: StableToken[] -) { - const accounts = Array.from( - new Array(Object.keys(TestAccounts).length / 2), - (_val, index) => index - ) - // Refund all to root - const root = await getKey(context.mnemonic, TestAccounts.Root) - context.logger.debug({ root: root.address }, 'Clearing funds of test accounts back to root') - const goldToken = await context.kit.contracts.getGoldToken() - await concurrentMap(5, accounts, async (_val, index) => { - if (index === 0) { - return - } - const account = await getKey(context.mnemonic, index) - context.kit.connection.addAccount(account.privateKey) - - const celoBalance = await goldToken.balanceOf(account.address) - // Exchange and transfer tests move ~0.5, so setting the threshold slightly below - const maxBalanceBeforeCollecting = ONE.times(0.4) - if (celoBalance.gt(maxBalanceBeforeCollecting)) { - await goldToken - .transfer( - root.address, - celoBalance - .minus(maxBalanceBeforeCollecting) - .integerValue(BigNumber.ROUND_DOWN) - .toString() - ) - .sendAndWaitForReceipt({ from: account.address, feeCurrency: undefined }) - context.logger.debug( - { - index, - value: celoBalance.toString(), - address: account.address, - }, - 'cleared CELO' - ) - } - for (const stableToken of stableTokensToClear) { - const stableTokenInstance = await context.kit.celoTokens.getWrapper(stableToken) - const balance = await stableTokenInstance.balanceOf(account.address) - if (balance.gt(maxBalanceBeforeCollecting)) { - await stableTokenInstance - .transfer( - root.address, - balance.minus(maxBalanceBeforeCollecting).integerValue(BigNumber.ROUND_DOWN).toString() - ) - .sendAndWaitForReceipt({ - feeCurrency: stableTokenInstance.address, - from: account.address, - }) - const balanceAfter = await stableTokenInstance.balanceOf(account.address) - context.logger.debug( - { - index, - stabletoken: stableToken, - balanceBefore: balance.toString(), - address: account.address, - BalanceAfter: balanceAfter.toString(), - }, - `cleared ${stableToken}` - ) - } - } - }) -} - -export function parseStableTokensList(stableTokenList: string): StableToken[] { - const stableTokenStrs = stableTokenList.split(',') - const validStableTokens = Object.values(StableToken) - - for (const stableTokenStr of stableTokenStrs) { - if (!validStableTokens.includes(stableTokenStr as StableToken)) { - throw Error(`String ${stableTokenStr} not a valid StableToken`) - } - } - return stableTokenStrs as StableToken[] -} diff --git a/packages/env-tests/src/tests/exchange.ts b/packages/env-tests/src/tests/exchange.ts deleted file mode 100644 index 8eafdbd41..000000000 --- a/packages/env-tests/src/tests/exchange.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { sleep } from '@celo/base' -import { StableToken } from '@celo/contractkit' -import { describe, test } from '@jest/globals' -import BigNumber from 'bignumber.js' -import { EnvTestContext } from '../context' -import { fundAccountWithStableToken, getKey, ONE, TestAccounts } from '../scaffold' - -export function runExchangeTest(context: EnvTestContext, stableTokensToTest: StableToken[]) { - describe('Exchange Test', () => { - const logger = context.logger.child({ test: 'exchange' }) - - for (const stableToken of stableTokensToTest) { - test(`exchange ${stableToken} for CELO`, async () => { - const stableTokenAmountToFund = ONE - await fundAccountWithStableToken( - context, - TestAccounts.Exchange, - stableTokenAmountToFund, - stableToken - ) - const stableTokenInstance = await context.kit.celoTokens.getWrapper(stableToken) - - const from = await getKey(context.mnemonic, TestAccounts.Exchange) - context.kit.connection.addAccount(from.privateKey) - context.kit.defaultAccount = from.address - context.kit.connection.defaultFeeCurrency = stableTokenInstance.address - const goldToken = await context.kit.contracts.getGoldToken() - - const exchange = await context.kit.contracts.getExchange(stableToken) - const previousGoldBalance = await goldToken.balanceOf(from.address) - const stableTokenAmountToSell = stableTokenAmountToFund.times(0.5) - const goldAmount = await exchange.getBuyTokenAmount(stableTokenAmountToSell, false) - logger.debug( - { rate: goldAmount.toString(), stabletoken: stableToken }, - `quote selling ${stableToken}` - ) - - const approveTx = await stableTokenInstance - .approve(exchange.address, stableTokenAmountToSell.toString()) - .send() - await approveTx.waitReceipt() - const sellTx = await exchange - .sell( - stableTokenAmountToSell, - // Allow 5% deviation from the quoted price - goldAmount.times(0.95).integerValue(BigNumber.ROUND_DOWN).toString(), - false - ) - .send() - await sellTx.getHash() - const receipt = await sellTx.waitReceipt() - logger.debug({ stabletoken: stableToken, receipt }, `Sold ${stableToken}`) - - const goldAmountToSell = (await goldToken.balanceOf(from.address)).minus( - previousGoldBalance - ) - - logger.debug( - { - goldAmount: goldAmount.toString(), - goldAmountToSell: goldAmountToSell.toString(), - stabletoken: stableToken, - }, - 'Loss to exchange' - ) - - const approveGoldTx = await goldToken - .approve(exchange.address, goldAmountToSell.toString()) - .send() - await approveGoldTx.waitReceipt() - await sleep(5000) - const sellGoldTx = await exchange - .sellGold( - goldAmountToSell, - // Assume we can get at least 80 % back - stableTokenAmountToSell.times(0.8).integerValue(BigNumber.ROUND_DOWN).toString() - ) - .send() - const sellGoldReceipt = await sellGoldTx.waitReceipt() - - logger.debug({ stabletoken: stableToken, receipt: sellGoldReceipt }, 'Sold CELO') - }) - } - }) -} diff --git a/packages/env-tests/src/tests/granda-mento.ts b/packages/env-tests/src/tests/granda-mento.ts deleted file mode 100644 index 81ef0b2d7..000000000 --- a/packages/env-tests/src/tests/granda-mento.ts +++ /dev/null @@ -1,263 +0,0 @@ -import { sleep } from '@celo/base' -import { StableToken } from '@celo/contractkit' -import { GoldTokenWrapper } from '@celo/contractkit/lib/wrappers/GoldTokenWrapper' -import { StableTokenWrapper } from '@celo/contractkit/lib/wrappers/StableTokenWrapper' -import { describe, test } from '@jest/globals' -import BigNumber from 'bignumber.js' -import Logger from 'bunyan' -import { EnvTestContext } from '../context' -import { - fundAccountWithCELO, - fundAccountWithStableToken, - getKey, - getValidatorKey, - ONE, - TestAccounts, -} from '../scaffold' - -export function runGrandaMentoTest(context: EnvTestContext, stableTokensToTest: StableToken[]) { - const celoAmountToFund = ONE.times(61000) - const stableTokenAmountToFund = ONE.times(61000) - - const celoAmountToSell = ONE.times(60000) - const stableTokenAmountToSell = ONE.times(60000) - - describe('Granda Mento Test', () => { - beforeAll(async () => { - await fundAccountWithCELO(context, TestAccounts.GrandaMentoExchanger, celoAmountToFund) - }) - - const baseLogger = context.logger.child({ test: 'grandaMento' }) - - for (const sellCelo of [true, false]) { - for (const stableToken of stableTokensToTest) { - const sellTokenStr = sellCelo ? 'CELO' : stableToken - const buyTokenStr = sellCelo ? stableToken : 'CELO' - describe(`selling ${sellTokenStr} for ${buyTokenStr}`, () => { - beforeAll(async () => { - if (!sellCelo) { - await fundAccountWithStableToken( - context, - TestAccounts.GrandaMentoExchanger, - stableTokenAmountToFund, - stableToken - ) - } - }) - - let buyToken: GoldTokenWrapper | StableTokenWrapper - let sellToken: GoldTokenWrapper | StableTokenWrapper - let stableTokenAddress: string - let sellAmount: BigNumber - - beforeEach(async () => { - const goldTokenWrapper = await context.kit.contracts.getGoldToken() - const stableTokenWrapper = await context.kit.celoTokens.getWrapper( - stableToken as StableToken - ) - stableTokenAddress = stableTokenWrapper.address - if (sellCelo) { - buyToken = stableTokenWrapper - sellToken = goldTokenWrapper - sellAmount = celoAmountToSell - } else { - buyToken = goldTokenWrapper - sellToken = stableTokenWrapper - sellAmount = stableTokenAmountToSell - } - }) - - const createExchangeProposal = async (logger: Logger, fromAddress: string) => { - const grandaMento = await context.kit.contracts.getGrandaMento() - const tokenApprovalReceipt = await sellToken - .approve(grandaMento.address, sellAmount.toFixed()) - .sendAndWaitForReceipt({ - from: fromAddress, - }) - logger.debug( - { - sellAmount, - sellTokenStr, - spender: grandaMento.address, - }, - 'Approved GrandaMento to spend sell token' - ) - const minedTokenApprovalTx = await context.kit.web3.eth.getTransaction( - tokenApprovalReceipt.transactionHash - ) - const tokenApprovalCeloFees = new BigNumber(tokenApprovalReceipt.gasUsed).times( - minedTokenApprovalTx.gasPrice - ) - - // Some flakiness has been observed after approving, so we sleep - await sleep(5000) - - const creationTx = await grandaMento.createExchangeProposal( - context.kit.celoTokens.getContract(stableToken as StableToken), - sellAmount, - sellCelo - ) - const creationReceipt = await creationTx.sendAndWaitForReceipt({ - from: fromAddress, - }) - // Some flakiness has been observed after proposing, so we sleep - await sleep(5000) - const proposalId = - creationReceipt.events!.ExchangeProposalCreated.returnValues.proposalId - - logger.debug( - { - sellAmount, - sellCelo, - proposalId, - }, - 'Created exchange proposal' - ) - const minedCreationTx = await context.kit.web3.eth.getTransaction( - creationReceipt.transactionHash - ) - const creationCeloFees = new BigNumber(creationReceipt.gasUsed).times( - minedCreationTx.gasPrice - ) - return { - creationReceipt, - minedCreationTx, - proposalId, - celoFees: tokenApprovalCeloFees.plus(creationCeloFees), - } - } - - test('exchanger creates and cancels an exchange proposal', async () => { - const from = await getKey(context.mnemonic, TestAccounts.GrandaMentoExchanger) - context.kit.connection.addAccount(from.privateKey) - context.kit.defaultAccount = from.address - - const logger = baseLogger.child({ from: from.address }) - const grandaMento = await context.kit.contracts.getGrandaMento() - - const sellTokenBalanceBeforeCreation = await sellToken.balanceOf(from.address) - - const creationInfo = await createExchangeProposal(logger, from.address) - let celoFees = creationInfo.celoFees - - const sellTokenBalanceAfterCreation = await sellToken.balanceOf(from.address) - - // If we are looking at the CELO balance, take the fees spent into consideration. - const expectedBalanceDifference = sellCelo ? sellAmount.plus(celoFees) : sellAmount - - expect( - sellTokenBalanceBeforeCreation.minus(sellTokenBalanceAfterCreation).toString() - ).toBe(expectedBalanceDifference.toString()) - - const cancelReceipt = await grandaMento - .cancelExchangeProposal(creationInfo.proposalId) - .sendAndWaitForReceipt({ - from: from.address, - }) - const minedCancelTx = await context.kit.web3.eth.getTransaction( - cancelReceipt.transactionHash - ) - - logger.debug( - { - proposalId: creationInfo.proposalId, - }, - 'Cancelled exchange proposal' - ) - - celoFees = celoFees.plus( - new BigNumber(cancelReceipt.gasUsed).times(minedCancelTx.gasPrice) - ) - - const sellTokenBalanceAfterCancel = await sellToken.balanceOf(from.address) - // If we are looking at the CELO balance, take the fees spent into consideration. - const expectedBalance = sellCelo - ? sellTokenBalanceBeforeCreation.minus(celoFees) - : sellTokenBalanceBeforeCreation - expect(sellTokenBalanceAfterCancel.toString()).toBe(expectedBalance.toString()) - }) - - test('exchanger creates and executes an approved exchange proposal', async () => { - const from = await getKey(context.mnemonic, TestAccounts.GrandaMentoExchanger) - context.kit.connection.addAccount(from.privateKey) - context.kit.defaultAccount = from.address - - const logger = baseLogger.child({ from: from.address }) - - const grandaMento = await context.kit.contracts.getGrandaMento() - - const sellTokenBalanceBefore = await sellToken.balanceOf(from.address) - const buyTokenBalanceBefore = await buyToken.balanceOf(from.address) - - const creationInfo = await createExchangeProposal(logger, from.address) - - const approver = await getValidatorKey(context.mnemonic, 0) - await grandaMento - .approveExchangeProposal(creationInfo.proposalId) - .sendAndWaitForReceipt({ - from: approver.address, - }) - - const vetoPeriodSeconds = await grandaMento.vetoPeriodSeconds() - // Sleep for the veto period, add 5 seconds for extra measure - const sleepPeriodMs = vetoPeriodSeconds.plus(5).times(1000).toNumber() - logger.debug( - { - sleepPeriodMs, - vetoPeriodSeconds, - }, - 'Sleeping so the veto period elapses' - ) - await sleep(sleepPeriodMs) - - // Executing from the approver to avoid needing to calculate additional gas paid - // by the approver in this test. - await grandaMento - .executeExchangeProposal(creationInfo.proposalId) - .sendAndWaitForReceipt({ - from: approver.address, - }) - - logger.debug( - { - proposalId: creationInfo.proposalId, - }, - 'Executed exchange proposal' - ) - - const sellTokenBalanceAfter = await sellToken.balanceOf(from.address) - let expectedSellTokenBalanceAfter = sellTokenBalanceBefore.minus(sellAmount) - if (sellCelo) { - expectedSellTokenBalanceAfter = expectedSellTokenBalanceAfter.minus( - creationInfo.celoFees - ) - } - expect(sellTokenBalanceAfter.toString()).toBe(expectedSellTokenBalanceAfter.toString()) - - const sortedOracles = await context.kit.contracts.getSortedOracles() - const celoStableTokenRate = (await sortedOracles.medianRate(stableTokenAddress)).rate - - const exchangeRate = sellCelo - ? celoStableTokenRate - : new BigNumber(1).div(celoStableTokenRate) - const buyAmount = getBuyAmount(exchangeRate, sellAmount, await grandaMento.spread()) - - const buyTokenBalanceAfter = await buyToken.balanceOf(from.address) - let expectedBuyTokenBalanceAfter = buyTokenBalanceBefore.plus(buyAmount) - if (!sellCelo) { - expectedBuyTokenBalanceAfter = expectedBuyTokenBalanceAfter.minus( - creationInfo.celoFees - ) - } - expect(buyTokenBalanceAfter.toString()).toBe(expectedBuyTokenBalanceAfter.toString()) - }) - }) - } - } - }) -} - -// exchangeRate is the price of the sell token quoted in buy token -function getBuyAmount(exchangeRate: BigNumber, sellAmount: BigNumber, spread: BigNumber.Value) { - return sellAmount.times(new BigNumber(1).minus(spread)).times(exchangeRate) -} diff --git a/packages/env-tests/src/tests/oracle.ts b/packages/env-tests/src/tests/oracle.ts deleted file mode 100644 index d1459e246..000000000 --- a/packages/env-tests/src/tests/oracle.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { CeloContract } from '@celo/contractkit' -import { describe, expect, test } from '@jest/globals' -import BigNumber from 'bignumber.js' -import { EnvTestContext } from '../context' -import { fundAccountWithcUSD, getKey, ONE, TestAccounts } from '../scaffold' - -export function runOracleTest(context: EnvTestContext) { - describe('Oracle Test', () => { - const logger = context.logger.child({ test: 'exchange' }) - beforeAll(async () => { - await fundAccountWithcUSD(context, TestAccounts.Exchange, ONE.times(2)) - }) - - // TODO: Check if oracle account is authorized - test('report a rate', async () => { - const from = await getKey(context.mnemonic, TestAccounts.Oracle) - context.kit.connection.addAccount(from.privateKey) - context.kit.defaultAccount = from.address - const stableToken = await context.kit.contracts.getStableToken() - context.kit.defaultFeeCurrency = stableToken.address - - const oracles = await context.kit.contracts.getSortedOracles() - - const isOracle = await oracles.isOracle(CeloContract.StableToken, from.address) - - expect(isOracle).toBeTruthy() - - const oracleRates = await oracles.getReports(CeloContract.StableToken) - const ourRate = oracleRates.find((_) => _.address === from.address) - - let rateToReport: BigNumber - if (!ourRate) { - const currentMedianRate = await oracles.medianRate(CeloContract.StableToken) - rateToReport = currentMedianRate.rate - logger.debug( - { - rate: currentMedianRate.rate.toString(), - }, - 'no existing rate, using the median' - ) - } else { - rateToReport = ourRate.rate - logger.debug({ rate: ourRate.rate.toString() }, 'fetched existing oracle report') - } - - // Move the rate in one direction or another - rateToReport = rateToReport.times(0.95 + Math.random() * 0.1).decimalPlaces(10) - - const reportTx = await oracles.report(CeloContract.StableToken, rateToReport, from.address) - const reportTxReceipt = await reportTx.sendAndWaitForReceipt({ from: from.address }) - logger.debug({ receipt: reportTxReceipt }, 'rate reported') - - const newOracleRates = await oracles.getReports(CeloContract.StableToken) - const ourNewRate = newOracleRates.find((_) => _.address === from.address) - - logger.debug({ rate: ourNewRate?.rate.toString() }, 'our new rate') - expect(ourNewRate?.rate).toEqual(rateToReport) - }) - }) -} diff --git a/packages/env-tests/src/tests/reserve.ts b/packages/env-tests/src/tests/reserve.ts deleted file mode 100644 index 8610207e3..000000000 --- a/packages/env-tests/src/tests/reserve.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { CeloContract } from '@celo/contractkit' -import { describe, test } from '@jest/globals' -import BigNumber from 'bignumber.js' -import { EnvTestContext } from '../context' -import { fundAccountWithcUSD, getKey, ONE, TestAccounts } from '../scaffold' -export function runReserveTest(context: EnvTestContext) { - describe('Reserve Test', () => { - const logger = context.logger.child({ test: 'reserve' }) - beforeAll(async () => { - await fundAccountWithcUSD(context, TestAccounts.ReserveSpender, ONE.times(2)) - await fundAccountWithcUSD(context, TestAccounts.ReserveCustodian, ONE.times(2)) - }) - - // TODO: Check if reserve account is authorized - test('move funds from the Reserve to a custodian and back', async () => { - const spender = await getKey(context.mnemonic, TestAccounts.ReserveSpender) - const custodian = await getKey(context.mnemonic, TestAccounts.ReserveCustodian) - context.kit.connection.addAccount(spender.privateKey) - context.kit.connection.addAccount(custodian.privateKey) - const reserve = await context.kit.contracts.getReserve() - const goldToken = await context.kit.contracts.getGoldToken() - - // Find an alternate way to get the reserve spender address - let spenderMultiSigAddress = context.reserveSpenderMultiSigAddress - - if (!spenderMultiSigAddress) { - context.logger.debug('have to get reserve spender multisig address') - const spenders = await reserve.getSpenders() - expect(spenders).toHaveLength(1) - spenderMultiSigAddress = spenders[0] - context.logger.debug({ spenderMultiSigAddress }, 'got reserve spender address') - } - - const custodians = await reserve.getOtherReserveAddresses() - expect(custodians).toContain(custodian.address) - - const spenderMultiSig = await context.kit.contracts.getMultiSig(spenderMultiSigAddress) - const isOwner = await spenderMultiSig.isowner(spender.address) - expect(isOwner).toBeTruthy() - - const reserveValue = await reserve.getReserveGoldBalance() - // Fetch from contract when added to CK wrapper - const dailySpendingRatio = 0.05 - const transferRatio = 0.01 - - const valueToTransfer = reserveValue - .times(dailySpendingRatio) - .times(transferRatio) - .integerValue(BigNumber.ROUND_DOWN) - const spenderTx = reserve.transferGold(custodian.address, valueToTransfer.toString()) - const multiSigTx = await spenderMultiSig.submitOrConfirmTransaction( - reserve.address, - spenderTx.txo - ) - logger.debug( - { - data: spenderTx.txo.encodeABI(), - reserve: reserve.address, - from: spenderMultiSigAddress, - }, - 'submitting via multisig' - ) - const multiSigTxReceipt = await multiSigTx.sendAndWaitForReceipt({ - from: spender.address, - feeCurrency: await context.kit.registry.addressFor(CeloContract.StableToken), - }) - - logger.debug({ receipt: multiSigTxReceipt }, 'funds moved to custodian via spender') - - const returnTx = goldToken.transfer(reserve.address, valueToTransfer.toString()) - const returnTxReceipt = await returnTx.sendAndWaitForReceipt({ from: custodian.address }) - - logger.debug({ receipt: returnTxReceipt }, 'funds moved back to reserve') - }) - }) -} diff --git a/packages/env-tests/src/tests/transfer.ts b/packages/env-tests/src/tests/transfer.ts deleted file mode 100644 index cf18e891b..000000000 --- a/packages/env-tests/src/tests/transfer.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { StableToken } from '@celo/contractkit' -import { describe, expect, test } from '@jest/globals' -import BigNumber from 'bignumber.js' -import { EnvTestContext } from '../context' -import { fundAccountWithStableToken, getKey, ONE, TestAccounts } from '../scaffold' - -export function runTransfersTest(context: EnvTestContext, stableTokensToTest: StableToken[]) { - describe('Transfer Test', () => { - const logger = context.logger.child({ test: 'transfer' }) - - for (const stableToken of stableTokensToTest) { - test(`transfer ${stableToken}`, async () => { - const stableTokenAmountToFund = ONE - await fundAccountWithStableToken( - context, - TestAccounts.TransferFrom, - stableTokenAmountToFund, - stableToken - ) - const stableTokenInstance = await context.kit.celoTokens.getWrapper(stableToken) - - const from = await getKey(context.mnemonic, TestAccounts.TransferFrom) - const to = await getKey(context.mnemonic, TestAccounts.TransferTo) - context.kit.connection.addAccount(from.privateKey) - context.kit.connection.addAccount(to.privateKey) - context.kit.connection.defaultFeeCurrency = stableTokenInstance.address - - const toBalanceBefore = await stableTokenInstance.balanceOf(to.address) - const fromBalanceBefore = await stableTokenInstance.balanceOf(from.address) - logger.debug( - { stabletoken: stableToken, balance: toBalanceBefore.toString(), account: to.address }, - `Get ${stableToken} Balance Before` - ) - - const stableTokenAmountToTransfer = ONE.times(0.5) - const receipt = await stableTokenInstance - .transfer(to.address, stableTokenAmountToTransfer.toString()) - .sendAndWaitForReceipt({ from: from.address }) - - logger.debug({ stabletoken: stableToken, receipt }, `Transferred ${stableToken}`) - const transaction = await context.kit.web3.eth.getTransaction(receipt.transactionHash) - const gasPrice = new BigNumber(transaction.gasPrice) - const gasUsed = new BigNumber(context.kit.web3.utils.toDecimal(receipt.gasUsed).toString()) - const transactionFee = gasPrice.times(gasUsed) - - const toBalanceAfter = await stableTokenInstance.balanceOf(to.address) - const fromBalanceAfter = await stableTokenInstance.balanceOf(from.address) - logger.debug( - { stabletoken: stableToken, balance: toBalanceAfter.toString(), account: to.address }, - `Get ${stableToken} Balance After` - ) - expect( - toBalanceAfter.minus(toBalanceBefore).isEqualTo(stableTokenAmountToTransfer) - ).toBeTruthy() - // check whether difference of balance of 'from' account before/after - transfer amount - // is equal to transaction fee - expect( - fromBalanceBefore - .minus(fromBalanceAfter) - .minus(stableTokenAmountToTransfer) - .isEqualTo(transactionFee) - ).toBeTruthy() - }) - } - }) -} diff --git a/packages/env-tests/tsconfig.json b/packages/env-tests/tsconfig.json deleted file mode 100644 index bee125824..000000000 --- a/packages/env-tests/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "../typescript/tsconfig.library.json", - "compilerOptions": { - "rootDir": "src", - "outDir": "lib", - "resolveJsonModule": true - }, - "include": ["src/**/*", "types/**/*", "src/utils/timezones.json", "../../node_modules/@celo/contractkit/types", "index.d.ts"], - "references": [{ "path": "../sdk/utils" }] -} diff --git a/packages/env-tests/tslint.json b/packages/env-tests/tslint.json deleted file mode 100644 index e4332b388..000000000 --- a/packages/env-tests/tslint.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "extends": ["@celo/typescript/tslint.json"], - "rules": {} -} diff --git a/packages/helm-charts/.gitignore b/packages/helm-charts/.gitignore deleted file mode 100644 index 71cbcd94c..000000000 --- a/packages/helm-charts/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -tracer-tool/staticnodes -*/charts -**/requirements.lock - diff --git a/packages/helm-charts/aad-pod-identity/Chart.yaml b/packages/helm-charts/aad-pod-identity/Chart.yaml deleted file mode 100644 index 8609750d4..000000000 --- a/packages/helm-charts/aad-pod-identity/Chart.yaml +++ /dev/null @@ -1,6 +0,0 @@ -name: aad-pod-identity -version: 0.1.1 -description: Helm v2 compatible helm chart for deploying aad-pod-identity -keywords: -- aad-pod-identity -appVersion: "" diff --git a/packages/helm-charts/aad-pod-identity/templates/azure-assigned-identity-crd.yaml b/packages/helm-charts/aad-pod-identity/templates/azure-assigned-identity-crd.yaml deleted file mode 100644 index f5887162a..000000000 --- a/packages/helm-charts/aad-pod-identity/templates/azure-assigned-identity-crd.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: azureassignedidentities.aadpodidentity.k8s.io -spec: - group: aadpodidentity.k8s.io - version: v1 - names: - kind: AzureAssignedIdentity - plural: azureassignedidentities - scope: Namespaced diff --git a/packages/helm-charts/aad-pod-identity/templates/azure-identity-binding-crd.yaml b/packages/helm-charts/aad-pod-identity/templates/azure-identity-binding-crd.yaml deleted file mode 100644 index 5f31afcd2..000000000 --- a/packages/helm-charts/aad-pod-identity/templates/azure-identity-binding-crd.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: azureidentitybindings.aadpodidentity.k8s.io -spec: - group: aadpodidentity.k8s.io - version: v1 - names: - kind: AzureIdentityBinding - plural: azureidentitybindings - scope: Namespaced diff --git a/packages/helm-charts/aad-pod-identity/templates/azure-identity-crd.yaml b/packages/helm-charts/aad-pod-identity/templates/azure-identity-crd.yaml deleted file mode 100644 index ff5e2f2f0..000000000 --- a/packages/helm-charts/aad-pod-identity/templates/azure-identity-crd.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: azureidentities.aadpodidentity.k8s.io -spec: - group: aadpodidentity.k8s.io - version: v1 - names: - kind: AzureIdentity - singular: azureidentity - plural: azureidentities - scope: Namespaced diff --git a/packages/helm-charts/aad-pod-identity/templates/azure-pod-identity-exception-crd.yaml b/packages/helm-charts/aad-pod-identity/templates/azure-pod-identity-exception-crd.yaml deleted file mode 100644 index 72bf54948..000000000 --- a/packages/helm-charts/aad-pod-identity/templates/azure-pod-identity-exception-crd.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: azurepodidentityexceptions.aadpodidentity.k8s.io -spec: - group: aadpodidentity.k8s.io - version: v1 - names: - kind: AzurePodIdentityException - singular: azurepodidentityexception - plural: azurepodidentityexceptions - scope: Namespaced diff --git a/packages/helm-charts/aad-pod-identity/templates/mic-cluster-role-binding.yaml b/packages/helm-charts/aad-pod-identity/templates/mic-cluster-role-binding.yaml deleted file mode 100644 index c5823c78f..000000000 --- a/packages/helm-charts/aad-pod-identity/templates/mic-cluster-role-binding.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: aad-pod-id-mic-binding - labels: - k8s-app: aad-pod-id-mic-binding -subjects: -- kind: ServiceAccount - name: aad-pod-id-mic-service-account - namespace: default -roleRef: - kind: ClusterRole - name: aad-pod-id-mic-role - apiGroup: rbac.authorization.k8s.io diff --git a/packages/helm-charts/aad-pod-identity/templates/mic-cluster-role.yaml b/packages/helm-charts/aad-pod-identity/templates/mic-cluster-role.yaml deleted file mode 100644 index c6ed7dbed..000000000 --- a/packages/helm-charts/aad-pod-identity/templates/mic-cluster-role.yaml +++ /dev/null @@ -1,29 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: aad-pod-id-mic-role -rules: -- apiGroups: ["apiextensions.k8s.io"] - resources: ["customresourcedefinitions"] - verbs: ["*"] -- apiGroups: [""] - resources: ["pods", "nodes"] - verbs: [ "list", "watch" ] -- apiGroups: [""] - resources: ["events"] - verbs: ["create", "patch"] -- apiGroups: [""] - resources: ["configmaps"] - verbs: ["get", "create", "update"] -- apiGroups: [""] - resources: ["endpoints"] - verbs: ["create", "get","update"] -- apiGroups: ["aadpodidentity.k8s.io"] - resources: ["azureidentitybindings", "azureidentities"] - verbs: ["get", "list", "watch", "post", "update"] -- apiGroups: ["aadpodidentity.k8s.io"] - resources: ["azurepodidentityexceptions"] - verbs: ["list", "update"] -- apiGroups: ["aadpodidentity.k8s.io"] - resources: ["azureassignedidentities"] - verbs: ["*"] diff --git a/packages/helm-charts/aad-pod-identity/templates/mic-deployment.yaml b/packages/helm-charts/aad-pod-identity/templates/mic-deployment.yaml deleted file mode 100644 index 7e4ee9d3c..000000000 --- a/packages/helm-charts/aad-pod-identity/templates/mic-deployment.yaml +++ /dev/null @@ -1,60 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - component: mic - k8s-app: aad-pod-id - name: mic -spec: - replicas: 2 - selector: - matchLabels: - component: mic - app: mic - template: - metadata: - labels: - component: mic - app: mic - annotations: - prometheus.io/scrape: "true" - prometheus.io/port: "{{ .Values.nmi.prometheusPort }}" - spec: - serviceAccountName: aad-pod-id-mic-service-account - containers: - - name: mic - image: {{ .Values.mic.image.repo }}:{{ .Values.mic.image.tag }} - imagePullPolicy: Always - args: - - "--syncRetryDuration={{ .Values.mic.syncRetryDuration }}" - - "--cloudconfig=/etc/kubernetes/azure.json" - - "--logtostderr" - - "--prometheus-port={{ .Values.mic.prometheusPort }}" - env: - - name: MIC_POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: FORCENAMESPACED - value: "{{ .Values.mic.forceNamespaced }}" - ports: - - name: prometheus - containerPort: {{ .Values.mic.prometheusPort }} - resources: -{{ toYaml .Values.mic.resources | indent 10 }} - volumeMounts: - - name: k8s-azure-file - mountPath: /etc/kubernetes/azure.json - readOnly: true - livenessProbe: - httpGet: - path: /healthz - port: 8080 - initialDelaySeconds: 10 - periodSeconds: 5 - volumes: - - name: k8s-azure-file - hostPath: - path: /etc/kubernetes/azure.json - nodeSelector: - beta.kubernetes.io/os: linux diff --git a/packages/helm-charts/aad-pod-identity/templates/mic-service-account.yaml b/packages/helm-charts/aad-pod-identity/templates/mic-service-account.yaml deleted file mode 100644 index ff5cf047c..000000000 --- a/packages/helm-charts/aad-pod-identity/templates/mic-service-account.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: aad-pod-id-mic-service-account - namespace: {{ .Values.namespace }} diff --git a/packages/helm-charts/aad-pod-identity/templates/nmi-cluster-role-binding.yaml b/packages/helm-charts/aad-pod-identity/templates/nmi-cluster-role-binding.yaml deleted file mode 100644 index 380e227b3..000000000 --- a/packages/helm-charts/aad-pod-identity/templates/nmi-cluster-role-binding.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: aad-pod-id-nmi-binding - labels: - k8s-app: aad-pod-id-nmi-binding -subjects: -- kind: ServiceAccount - name: aad-pod-id-nmi-service-account - namespace: default -roleRef: - kind: ClusterRole - name: aad-pod-id-nmi-role - apiGroup: rbac.authorization.k8s.io diff --git a/packages/helm-charts/aad-pod-identity/templates/nmi-cluster-role.yaml b/packages/helm-charts/aad-pod-identity/templates/nmi-cluster-role.yaml deleted file mode 100644 index 7145aec03..000000000 --- a/packages/helm-charts/aad-pod-identity/templates/nmi-cluster-role.yaml +++ /dev/null @@ -1,20 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: aad-pod-id-nmi-role -rules: -- apiGroups: ["apiextensions.k8s.io"] - resources: ["customresourcedefinitions"] - verbs: ["get", "list"] -- apiGroups: [""] - resources: ["pods"] - verbs: ["get", "list", "watch"] -- apiGroups: [""] - resources: ["secrets"] - verbs: ["get"] -- apiGroups: ["aadpodidentity.k8s.io"] - resources: ["azureidentitybindings", "azureidentities", "azurepodidentityexceptions"] - verbs: ["get", "list", "watch"] -- apiGroups: ["aadpodidentity.k8s.io"] - resources: ["azureassignedidentities"] - verbs: ["get", "list", "watch"] diff --git a/packages/helm-charts/aad-pod-identity/templates/nmi-daemonset.yaml b/packages/helm-charts/aad-pod-identity/templates/nmi-daemonset.yaml deleted file mode 100644 index c28d055c8..000000000 --- a/packages/helm-charts/aad-pod-identity/templates/nmi-daemonset.yaml +++ /dev/null @@ -1,78 +0,0 @@ -apiVersion: apps/v1 -kind: DaemonSet -metadata: - labels: - component: nmi - tier: node - k8s-app: aad-pod-id - name: nmi -spec: - updateStrategy: - type: RollingUpdate - selector: - matchLabels: - component: nmi - tier: node - template: - metadata: - labels: - component: nmi - tier: node - annotations: - prometheus.io/scrape: "true" - prometheus.io/port: "{{ .Values.nmi.prometheusPort }}" - spec: - serviceAccountName: aad-pod-id-nmi-service-account - hostNetwork: true - volumes: - - hostPath: - path: /run/xtables.lock - type: FileOrCreate - name: iptableslock - containers: - - name: nmi - image: {{ .Values.nmi.image.repo }}:{{ .Values.nmi.image.tag }} - imagePullPolicy: Always - args: - {{- if semverCompare "<= 1.6.1-0" .Values.nmi.image.tag }} - - "--host-ip=$(HOST_IP)" - {{- end }} - - "--node=$(NODE_NAME)" - - "--prometheus-port={{ .Values.nmi.prometheusPort }}" - {{- if .Values.nmi.probePort }} - - --http-probe-port={{ .Values.nmi.probePort }} - {{- end }} - env: - {{- if semverCompare "<= 1.6.1-0" .Values.nmi.image.tag }} - - name: HOST_IP - valueFrom: - fieldRef: - fieldPath: status.podIP - {{- end }} - - name: NODE_NAME - valueFrom: - fieldRef: - fieldPath: spec.nodeName - - name: FORCENAMESPACED - value: "{{ .Values.nmi.forceNamespaced }}" - ports: - - name: prometheus - containerPort: {{ .Values.nmi.prometheusPort }} - resources: -{{ toYaml .Values.nmi.resources | indent 10 }} - securityContext: - privileged: true - capabilities: - add: - - NET_ADMIN - volumeMounts: - - mountPath: /run/xtables.lock - name: iptableslock - livenessProbe: - httpGet: - path: /healthz - port: 8080 - initialDelaySeconds: 10 - periodSeconds: 5 - nodeSelector: - beta.kubernetes.io/os: linux diff --git a/packages/helm-charts/aad-pod-identity/templates/nmi-service-account.yaml b/packages/helm-charts/aad-pod-identity/templates/nmi-service-account.yaml deleted file mode 100644 index c6e28537b..000000000 --- a/packages/helm-charts/aad-pod-identity/templates/nmi-service-account.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: aad-pod-id-nmi-service-account diff --git a/packages/helm-charts/aad-pod-identity/values.yaml b/packages/helm-charts/aad-pod-identity/values.yaml deleted file mode 100644 index caa43c2df..000000000 --- a/packages/helm-charts/aad-pod-identity/values.yaml +++ /dev/null @@ -1,30 +0,0 @@ -namespace: default - -nmi: - forceNamespaced: true - prometheusPort: 9090 - probePort: 8080 - image: - repo: mcr.microsoft.com/k8s/aad-pod-identity/nmi - tag: 1.6.2 - resources: - limits: - cpu: 200m - memory: 512Mi - requests: - cpu: 100m - memory: 256Mi -mic: - syncRetryDuration: 1m - forceNamespaced: true - prometheusPort: 9090 - image: - repo: mcr.microsoft.com/k8s/aad-pod-identity/mic - tag: 1.6.2 - resources: - limits: - cpu: 200m - memory: 1024Mi - requests: - cpu: 100m - memory: 256Mi diff --git a/packages/helm-charts/celo-fullnode/README.md b/packages/helm-charts/celo-fullnode/README.md deleted file mode 100644 index c7c79f993..000000000 --- a/packages/helm-charts/celo-fullnode/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# celo-fullnode - -Moved to https://github.com/celo-org/charts/tree/main/charts/celo-fullnode diff --git a/packages/helm-charts/celo-fullnode/baklava-gcp-forno-europe-west1-values.yaml b/packages/helm-charts/celo-fullnode/baklava-gcp-forno-europe-west1-values.yaml deleted file mode 100644 index 7888c91e7..000000000 --- a/packages/helm-charts/celo-fullnode/baklava-gcp-forno-europe-west1-values.yaml +++ /dev/null @@ -1,5 +0,0 @@ -geth: - resources: - requests: - memory: "2Gi" - cpu: "1" diff --git a/packages/helm-charts/celo-fullnode/rc1-blockscout-archive-nodes.yaml b/packages/helm-charts/celo-fullnode/rc1-blockscout-archive-nodes.yaml deleted file mode 100644 index a1c9dc217..000000000 --- a/packages/helm-charts/celo-fullnode/rc1-blockscout-archive-nodes.yaml +++ /dev/null @@ -1,117 +0,0 @@ -extraPodLabels: - stack: blockscout - mode: archive -gcp: true -genesis: - network: mainnet - networkId: 42220 - useGenesisFileBase64: false -geth: - autoscaling: - enabled: true - flags: --txpool.nolocals - gcmode: archive - image: - repository: us.gcr.io/celo-org/geth - tag: 1.6.0 - light: - maxpeers: 100 - serve: 10 - maxpeers: 300 - node_keys: - - f4486a87798a9126713c146cd509254facc106dda552bd40962a7082e26d4460 - - 5b21d503b04d249adf9a4e6ce21d44989b2db354f159efee5fd33d561092a002 - - fc97615d43b667355ee2f552f8f948b1ed5a9d7c30200373da718d336a3a26da - - a15274c6dca70162871ef29a39b3a62256ce0bbf99ebbae389e1377f5c30f08c - - dc485cf3ff51fab4c06ec9bcb4a603d3695bf05e03520fdbab623265d9b63052 - - ef250753e59d89aab92c1f27ff3752b3aca89a88042792fbba58b88c2c4e66f4 - - 34097470523dec7fad6b1c410bed2db8bc7230defb0f59a9273f1f77526f4758 - - 3d043585fc9e17231234f44072c96b635d65f30791a8176fc5a80e889aa0903d - - cc711146c6b5894994f8765ffa42a83c4ca1656e81c654c8345f76c2635c6f4e - - ad76caee7ef9e42f61507e2c8529319f40a61a5b455a9d1031692a92ce415965 - - ef15f6d4279f2b2bc3a4c9a7a452678f5fa8c8b07d03ec76bc6bd50190aaee1d - - dd66a303cbbf1c98b5bcd56243ae4e24e60dec5174b11f87fab549c4f80fd198 - - d7a242bf77ab1bd12f5442c932686b000d99cd2ee4bc923ca01b398c6b57db6b - - 4062c9fa13f2ffec078505af8248062215347032ce2b741c470a1f36774273b8 - - d264a62bfe34d53cd2c9dc58898ab19147a13538bbfb24d31e02214d7a927c3b - - 78b97813b660129f12366da15ff9e81c586ea354468c652fc65dfcee40abb814 - - 44a8b95c09f4ccc3f415f7a11824a82fb6288224efa773f3091b750d52b0cbe0 - - 8f5cbf90cf7cf071557ff637804fa11550199555899f6253533e23151590e5ed - - f9c35ab423b6db764e756d5f77ce5132cf5b820a4be88bc278c0754f174728ec - - 7ad8d862501c4c7de1654a96bcf23eedcfdc04b8a95195da4089d185abdf60ef - - 8aef854cfac6841c199bc767abe7d2eadfda6073a61f34894b3da00e036ad5f0 - - cd67d0045352cd7fd51bbc34a6af187326e325db0c0ad6cdcce51a33a38cffd8 - - ab30ca2331d3d6a9ff455ff9a3f077e143fe01e6593b8e42cd4b0aa2350f9a9e - - 8408dcd47dcb987c4c89033f7b8506901c66e181a10458ebcc91eeef982c2582 - - 202b60fdb9353776f8f4e00225ff02115d666540a56cf549d30818e299cd4d59 - - 8d29fa939f8941c49b4f07b0ad0a97c6eb239e5880692a072d4e1be2c463b4b0 - - 9f803e572b044fdfae9c7f3e74dee7c2162d233ba423693334008125a648b274 - - 0386a0924d55c55e7ede22f2e9e97d6d35f5701131d8731fd0da151126806ffd - - 0b2fd5138854399a8219b0dd1784f244b9f9fc296d181d298a32867187b16a67 - - 0182756023478f62374dd687afdccfd51851486377accc96f4a4c1db25744f99 - - 3fe6b563d9716770e0299118fca2ba1ccc7614790d34ab2edb1641a5746985df - - f2a08b997813997b0bdda27fba307febf289d74b447fc2249034fe871a6f49c7 - - 22c0c78eb636490dd207314752e1688c54904d1f0f30fdc3a4def0546e4901ed - - f1c92539640b122db86c32bf746174bcaa54c9ee0824ea68aef1d625721b3f68 - - b8674e3f79f79790209c4e75040e31ce321184085c8d49b71341a45c86b050bc - - f2939dbec209f51467e406a4e80884e074c533bafe378cced62a19f14f454e73 - - 8bad5dbd251fd52499ded9ce5e4944dbd1f9d6208546537763998051c49f8f91 - - 71d8c4e8ac3611f208e0f01391738d3f6146be3f1f535aae0d54aa66de83caad - - 069163e28ee56776b26d354831586422ca84e01c500f158709b413c76fb2a68e - - 1c83157e1c8dd52ea9f826c15acc8c8a4de3338746ab411386879135440b3085 - - 5eba03f3b36e92b711d58b6fa9a66c8342c86cabe11ab748f4a66fa504c3e9ff - - 04851878b38b9509de08f7c02bc49f949937cd5dabb6aea71c552f4f86734d1f - - 00c3206352cb7b855ed72675e62192f07cef72717b8cacf1add709d46acd7a89 - - c37112d3e511aff3113512b46a1433ebe473c4bbf55aeca33c321c64bf075dd8 - - 9584d2a83be292abd8de0332af9c5fc327e98ee4f190340f30a9cd7a65ae606d - - cd81f5f300e8fe070e7c5b867a1c2a531f5d4c3d1b7a1b1b49258c6e4289be13 - - 82bfe2e82c3ee2331cbbe14ca03a286b19c691785d7db8d4213919b4a970e5c4 - - 08508d726d3d592e922324eacdcf622480a479c61a0414e47b59e219b7c3c245 - - 0176d2e8d1a3fc60f2cc55265ebe2bfb04074521d52b1fb844e2fe28646f604b - - 53cc64a704ac5712d1990efd511571d4b22a566c1c184731dda57c04acc815c9 - public_ip_per_node: - - 34.168.166.173 - - 34.168.53.31 - - 34.168.142.153 - - 104.196.248.95 - - 34.168.14.34 - - 35.199.167.145 - - 34.168.58.236 - - 34.168.208.61 - - 35.230.20.151 - - 35.203.178.255 - resources: - requests: - cpu: "7" - memory: 24Gi - rpc_apis: eth,net,rpc,web3 - service_protocols: - - TCP - - UDP - service_type: LoadBalancer - use_gstorage_data: false - verbosity: 2 - ws_port: 8545 -ingress: - enabled: false -namespace: blockscout - -metrics: true -prometheus: true -replicaCount: 2 -storage: - accessModes: ReadWriteOnce - enable: true - size: 1500Gi - snapshot: - enabled: true - kind: VolumeSnapshot - name: snapshot-archive-node-blockscout - storageClass: premium-rwo -nodeSelector: - pool: t2d-standard-8-spot -tolerations: -- effect: NoSchedule - key: pool - operator: Equal - value: t2d-standard-8-spot diff --git a/packages/helm-charts/celo-fullnode/rc1-gcp-private-txnodes-values.yaml b/packages/helm-charts/celo-fullnode/rc1-gcp-private-txnodes-values.yaml deleted file mode 100644 index fd6489219..000000000 --- a/packages/helm-charts/celo-fullnode/rc1-gcp-private-txnodes-values.yaml +++ /dev/null @@ -1,19 +0,0 @@ -geth: - resources: - requests: - memory: "21Gi" - cpu: "7" - service_session_affinity: None - node_keys: - - "28406f9c37274e163f5f3335fec2a35e0d3bf3895c28f7a54dd8ecd614d1437c" - - "7c0b1c0518bdd3e1a0db8b0ed6999e4404b344a950462fda42ab53ca7ccea271" - - "e658b12507dc91948440e15dc5f85d670b9c55a6ec0ad6e11f87a2eacebf07c5" - - "3d9a4d83ac67bef79558fe49993ac0436fa15a64b9d383a77c808d0653911722" - - "eb8a93871d8ae965484e00d6381cd3756dc13381a98bf715456f0a7dd940ad9e" - - "87d3a7ce70fc43db4a070a0db1b69ac78f8db0e10163e34248347966b3a8b072" - - "e7565adbdfab09dab769148a34da35168ababecbba6a468d21ccd9fcff9b5946" - - "09e2c8c304c5019c5569f27ceea3f1d6d97facbdf8fe410831cd3c615e5df82f" - -extraPodLabels: - stack: blockscout - mode: archive diff --git a/packages/helm-charts/celo-fullnode/rc1staging-archivenodes-values.yaml b/packages/helm-charts/celo-fullnode/rc1staging-archivenodes-values.yaml deleted file mode 100644 index ff67901e7..000000000 --- a/packages/helm-charts/celo-fullnode/rc1staging-archivenodes-values.yaml +++ /dev/null @@ -1,36 +0,0 @@ -fullnameOverride: rc1staging-archivenodes -gcp: true -genesis: - network: rc1 - networkId: 42220 -geth: - gcmode: archive - image: - imagePullPolicy: IfNotPresent - repository: us.gcr.io/celo-org/geth - tag: 1.5.6 - light: - maxpeers: 1000 - serve: 90 - maxpeers: 1100 - node_keys: - - 5781152a2ab09ae18dd0a48baacc743c9b05f7542d6207615c86dd9bc21b5c94 - - 609a06841bbf4e7579ee804d9422094f2401d455b8834336a3faea3545950fa8 - public_ip_per_node: [] # needs to be provided - resources: - requests: - cpu: "7" - memory: 21Gi - rpc_apis: eth,net,rpc,web3,txpool,debug - service_type: None - use_gstorage_data: false - ws_port: 8545 - increase_timeouts: true -namespace: rc1staging -replicaCount: 2 -storage: - size: 1500Gi - storageClass: ssd -extraPodLabels: - stack: blockscout - mode: archive diff --git a/packages/helm-charts/celostats/Chart.yaml b/packages/helm-charts/celostats/Chart.yaml deleted file mode 100644 index 89630c7b9..000000000 --- a/packages/helm-charts/celostats/Chart.yaml +++ /dev/null @@ -1,11 +0,0 @@ ---- -name: celostats -apiVersion: v1 -version: 0.1.0 -description: Chart which is used to deploy an celostats setup for a celo testnet -keywords: - - ethereum - - blockchain - - celostats - - ethstats -appVersion: "" diff --git a/packages/helm-charts/celostats/README.md b/packages/helm-charts/celostats/README.md deleted file mode 100644 index a9b153a2e..000000000 --- a/packages/helm-charts/celostats/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# celostats - -## Deploying on existing testnet - -This helm chart is an evolution from the former `ethstats` chart. -This chart includes artifacts for deploying the artifacts of -`celostats-server` (https://github.com/celo-org/celostats-server/) and -`celostats-frontend` (https://github.com/celo-org/celostats-frontend/). -Also, for compatibility reasons, include an ingress resource serving -at DNS `https://ethstats-${env}.${celo-domain}`, so the old-configured -clients can report/connect with that endpoint. - -To upgrade from an exisiting `ethstats` package, the easiest way is: - -1. Remove the old `ethstats` package: `helm uninstall --purge ${env}-ethstats` - -2. Deploy the new package: `celotool deploy initial celostats -e ${env}` diff --git a/packages/helm-charts/celostats/templates/celostats-frontend.deployment.yaml b/packages/helm-charts/celostats/templates/celostats-frontend.deployment.yaml deleted file mode 100644 index 3fdc2fc19..000000000 --- a/packages/helm-charts/celostats/templates/celostats-frontend.deployment.yaml +++ /dev/null @@ -1,57 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ .Release.Namespace }}-celostats-frontend - labels: - app: celostats - chart: celostats - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - component: celostats-frontend -spec: - replicas: 1 - selector: - matchLabels: - app: celostats - release: {{ .Release.Name }} - component: celostats-frontend - template: - metadata: - labels: - app: celostats - release: {{ .Release.Name }} - component: celostats-frontend - spec: - containers: - - name: celostats-frontend - image: {{ .Values.celostats.image.frontend.repository }}:{{ .Values.celostats.image.frontend.tag }} - imagePullPolicy: {{ .Values.imagePullPolicy }} - env: - - name: ETHSTATS_SERVICE - value: https://{{ .Release.Namespace }}-celostats-server.{{ .Values.domain.name }}.org - - name: BLOCKSCOUT_URL - value: https://{{ .Release.Namespace }}-blockscout.{{ .Values.domain.name }}.org - - name: SUBMENU_BLOCKSCOUT - value: https://{{ .Release.Namespace }}-blockscout.{{ .Values.domain.name }}.org - - name: GRAPHQL_BLOCKSCOUT_URL - value: https://{{ .Release.Namespace }}-blockscout.{{ .Values.domain.name }}.org/graphiql - command: - - /bin/sh - - -c - args: - - | - /var/www/scripts/set-env-variables.js /var/www/app - ngsw-config /var/www/app/ /var/www/ngsw-config.json - exec nginx -g "daemon off;" - ports: - - name: http - containerPort: 80 - protocol: TCP - {{- with .Values.resources.frontend }} - resources: - {{- toYaml . | nindent 10 }} - {{- end }} - {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} diff --git a/packages/helm-charts/celostats/templates/celostats-frontend.ingress.yaml b/packages/helm-charts/celostats/templates/celostats-frontend.ingress.yaml deleted file mode 100644 index f84fc7964..000000000 --- a/packages/helm-charts/celostats/templates/celostats-frontend.ingress.yaml +++ /dev/null @@ -1,29 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: {{ .Release.Namespace }}-celostats-frontend - labels: - app: celostats - chart: celostats - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - component: celostats-frontend - annotations: - kubernetes.io/tls-acme: "true" -spec: - ingressClassName: {{ default "nginx" .Values.ingressClassName }} - tls: - - hosts: - - {{ .Release.Namespace }}-celostats.{{ .Values.domain.name }}.org - secretName: {{ .Release.Namespace }}-celostats-frontend-tls - rules: - - host: {{ .Release.Namespace }}-celostats.{{ .Values.domain.name }}.org - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: {{ .Release.Namespace }}-celostats-frontend - port: - number: 80 diff --git a/packages/helm-charts/celostats/templates/celostats-frontend.service.yaml b/packages/helm-charts/celostats/templates/celostats-frontend.service.yaml deleted file mode 100644 index d54dc5c79..000000000 --- a/packages/helm-charts/celostats/templates/celostats-frontend.service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -kind: Service -apiVersion: v1 -metadata: - name: {{ .Release.Namespace }}-celostats-frontend - labels: - app: celostats - chart: celostats - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - component: celostats-frontend -spec: - selector: - app: celostats - release: {{ .Release.Name }} - component: celostats-frontend - type: {{ .Values.celostats.service.type }} - ports: - - port: 80 - targetPort: http diff --git a/packages/helm-charts/celostats/templates/celostats-server.deployment.yaml b/packages/helm-charts/celostats/templates/celostats-server.deployment.yaml deleted file mode 100644 index fb3bc22bd..000000000 --- a/packages/helm-charts/celostats/templates/celostats-server.deployment.yaml +++ /dev/null @@ -1,56 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ .Release.Namespace }}-celostats-server - labels: - app: celostats - chart: celostats - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - component: celostats-server -spec: - replicas: 1 - selector: - matchLabels: - app: celostats - release: {{ .Release.Name }} - component: celostats-server - template: - metadata: - labels: - app: celostats - release: {{ .Release.Name }} - component: celostats-server - spec: - containers: - - name: celostats-server - image: {{ .Values.celostats.image.server.repository }}:{{ .Values.celostats.image.server.tag }} - imagePullPolicy: {{ .Values.imagePullPolicy }} - env: - - name: TRUSTED_ADDRESSES - value: {{ .Values.celostats.trusted_addresses }} - - name: BANNED_ADDRESSES - value: {{ .Values.celostats.banned_addresses }} - - name: RESERVED_ADDRESSES - value: {{ .Values.celostats.reserved_addresses }} - - name: JSONRPC - value: {{ .Values.celostats.jsonrpc }} - command: - - /bin/sh - - -c - args: - - | - sed -i "s%###NETWORK_NAME###%{{ .Values.celostats.network_name }}%g" /celostats-server/dist/js/netstats.min.js - sed -i "s%###BLOCKSCOUT_URL###%{{ .Values.celostats.blockscout_url }}%g" /celostats-server/dist/js/netstats.min.js - exec npm start - ports: - - name: http - containerPort: 3000 - {{- with .Values.resources.server }} - resources: - {{- toYaml . | nindent 10 }} - {{- end }} - {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} diff --git a/packages/helm-charts/celostats/templates/celostats-server.ingress.yaml b/packages/helm-charts/celostats/templates/celostats-server.ingress.yaml deleted file mode 100644 index 820ba805f..000000000 --- a/packages/helm-charts/celostats/templates/celostats-server.ingress.yaml +++ /dev/null @@ -1,29 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: {{ .Release.Namespace }}-celostats-server - labels: - app: celostats - chart: celostats - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - component: celostats-server - annotations: - kubernetes.io/tls-acme: "true" -spec: - ingressClassName: {{ default "nginx" .Values.ingressClassName }} - tls: - - hosts: - - {{ .Release.Namespace }}-celostats-server.{{ .Values.domain.name }}.org - secretName: {{ .Release.Namespace }}-celostats-tls - rules: - - host: {{ .Release.Namespace }}-celostats-server.{{ .Values.domain.name }}.org - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: {{ .Release.Namespace }}-celostats-server - port: - number: 80 diff --git a/packages/helm-charts/celostats/templates/celostats-server.service.yaml b/packages/helm-charts/celostats/templates/celostats-server.service.yaml deleted file mode 100644 index b03e53737..000000000 --- a/packages/helm-charts/celostats/templates/celostats-server.service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -kind: Service -apiVersion: v1 -metadata: - name: {{ .Release.Namespace }}-celostats-server - labels: - app: celostats - chart: celostats - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - component: celostats-server -spec: - selector: - app: celostats - release: {{ .Release.Name }} - component: celostats-server - type: {{ .Values.celostats.service.type }} - ports: - - port: 80 - targetPort: http diff --git a/packages/helm-charts/celostats/templates/ethstats.ingress.yaml b/packages/helm-charts/celostats/templates/ethstats.ingress.yaml deleted file mode 100644 index b1359bc86..000000000 --- a/packages/helm-charts/celostats/templates/ethstats.ingress.yaml +++ /dev/null @@ -1,33 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: {{ .Release.Namespace }}-ethstats-ingress - labels: - app: celostats - chart: celostats - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - component: ethstats - annotations: - kubernetes.io/tls-acme: "true" - nginx.ingress.kubernetes.io/configuration-snippet: | - if ($http_upgrade != "websocket") { - return 301 https://{{ .Release.Namespace }}-celostats.{{ .Values.domain.name }}.org/; - } -spec: - ingressClassName: {{ default "nginx" .Values.ingressClassName }} - tls: - - hosts: - - {{ .Release.Namespace }}-ethstats.{{ .Values.domain.name }}.org - secretName: {{ .Release.Namespace }}-ethstats-tls - rules: - - host: {{ .Release.Namespace }}-ethstats.{{ .Values.domain.name }}.org - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: {{ .Release.Namespace }}-celostats-server - port: - number: 80 diff --git a/packages/helm-charts/celostats/templates/ethstats.service.yaml b/packages/helm-charts/celostats/templates/ethstats.service.yaml deleted file mode 100644 index d7fc6d67e..000000000 --- a/packages/helm-charts/celostats/templates/ethstats.service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -kind: Service -apiVersion: v1 -metadata: - name: {{ .Release.Namespace }}-ethstats - labels: - app: celostats - chart: celostats - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - component: ethstats -spec: - selector: - app: celostats - release: {{ .Release.Name }} - component: celostats-server - type: {{ .Values.celostats.service.type }} - ports: - - port: 80 - targetPort: http diff --git a/packages/helm-charts/celostats/values.yaml b/packages/helm-charts/celostats/values.yaml deleted file mode 100644 index ad82aa6aa..000000000 --- a/packages/helm-charts/celostats/values.yaml +++ /dev/null @@ -1,35 +0,0 @@ -imagePullPolicy: IfNotPresent - -# Node labels for pod assignment -# ref: https://kubernetes.io/docs/user-guide/node-selection/ -nodeSelector: {} - -celostats: - image: - server: - repository: gcr.io/celo-testnet/celostats-server - tag: latest - frontend: - repository: gcr.io/celo-testnet/celostats-frontend - tag: latest - service: - type: NodePort - trusted_addresses: [] - banned_addresses: [] - -domain: - name: celo-testnet - -ingressClassName: nginx - -resources: - server: - requests: - cpu: 15m - memory: 110Mi - limits: {} - frontend: - requests: - cpu: 1m - memory: 5Mi - limits: {} diff --git a/packages/helm-charts/cert-manager-cluster-issuers/Chart.yaml b/packages/helm-charts/cert-manager-cluster-issuers/Chart.yaml deleted file mode 100644 index 8efa04fff..000000000 --- a/packages/helm-charts/cert-manager-cluster-issuers/Chart.yaml +++ /dev/null @@ -1,12 +0,0 @@ -name: cert-manager-issuers -apiVersion: v2 -version: 0.2.0 -description: Chart which is used to deploy let's encrypt issuers -keywords: -- "let's encrypt" -- cert-manager -appVersion: v1.7.3 -dependencies: - - name: cert-manager - version: v1.9.1 - repository: https://charts.jetstack.io diff --git a/packages/helm-charts/cert-manager-cluster-issuers/README.md b/packages/helm-charts/cert-manager-cluster-issuers/README.md deleted file mode 100644 index d64c1bd61..000000000 --- a/packages/helm-charts/cert-manager-cluster-issuers/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# cert-manager-cluster-issuers - -This is the newer version of kube-lego that automatically gets SSL certificates. -This specifies staging & production ClusterIssuers. diff --git a/packages/helm-charts/cert-manager-cluster-issuers/templates/prod.clusterissuer.yaml b/packages/helm-charts/cert-manager-cluster-issuers/templates/prod.clusterissuer.yaml deleted file mode 100644 index a6d42aaf6..000000000 --- a/packages/helm-charts/cert-manager-cluster-issuers/templates/prod.clusterissuer.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: cert-manager.io/v1 -kind: ClusterIssuer -metadata: - name: letsencrypt-prod -spec: - acme: - # The ACME server URL - server: https://acme-v02.api.letsencrypt.org/directory - # Email address used for ACME registration - email: n@celo.org - # Name of a secret used to store the ACME account private key - privateKeySecretRef: - name: letsencrypt-prod - # Enable the HTTP-01 challenge provider - solvers: - - http01: - ingress: - class: nginx diff --git a/packages/helm-charts/cert-manager-cluster-issuers/templates/staging.clusterissuer.yaml b/packages/helm-charts/cert-manager-cluster-issuers/templates/staging.clusterissuer.yaml deleted file mode 100644 index c86e91b3a..000000000 --- a/packages/helm-charts/cert-manager-cluster-issuers/templates/staging.clusterissuer.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: cert-manager.io/v1 -kind: ClusterIssuer -metadata: - name: letsencrypt-staging -spec: - acme: - # The ACME server URL - server: https://acme-staging-v02.api.letsencrypt.org/directory - # Email address used for ACME registration - email: n@celo.org - # Name of a secret used to store the ACME account private key - privateKeySecretRef: - name: letsencrypt-staging - # Enable the HTTP-01 challenge provider - solvers: - - http01: - ingress: - class: nginx diff --git a/packages/helm-charts/cert-manager-cluster-issuers/values.yaml b/packages/helm-charts/cert-manager-cluster-issuers/values.yaml deleted file mode 100644 index d03351f2b..000000000 --- a/packages/helm-charts/cert-manager-cluster-issuers/values.yaml +++ /dev/null @@ -1,9 +0,0 @@ -imagePullPolicy: IfNotPresent - -# Values that are used for the dependency `cert-manager` -cert-manager: - ingressShim: - defaultIssuerKind: ClusterIssuer - defaultIssuerName: letsencrypt-prod - webhook: - enabled: false diff --git a/packages/helm-charts/common/README.md b/packages/helm-charts/common/README.md deleted file mode 100644 index e61ab2c96..000000000 --- a/packages/helm-charts/common/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# common - -Moved to https://github.com/celo-org/charts/tree/main/charts/common diff --git a/packages/helm-charts/gcp-ssd/Chart.yaml b/packages/helm-charts/gcp-ssd/Chart.yaml deleted file mode 100644 index 736e3893d..000000000 --- a/packages/helm-charts/gcp-ssd/Chart.yaml +++ /dev/null @@ -1,8 +0,0 @@ -name: gcp-ssd -version: 0.0.1 -description: Chart to deploy a GCP SSD storage class -keywords: -- gcp -- ssd -- storage-class -appVersion: v1.7.3 diff --git a/packages/helm-charts/gcp-ssd/templates/storage-class.yaml b/packages/helm-charts/gcp-ssd/templates/storage-class.yaml deleted file mode 100644 index 62500d87f..000000000 --- a/packages/helm-charts/gcp-ssd/templates/storage-class.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: storage.k8s.io/v1 -kind: StorageClass -metadata: - name: ssd -provisioner: kubernetes.io/gce-pd -parameters: - type: pd-ssd diff --git a/packages/helm-charts/grafana/values-clabs.yaml b/packages/helm-charts/grafana/values-clabs.yaml deleted file mode 100644 index 8f27dc226..000000000 --- a/packages/helm-charts/grafana/values-clabs.yaml +++ /dev/null @@ -1,46 +0,0 @@ -annotations: - prometheus.io/path: /metrics - prometheus.io/port: "3000" - prometheus.io/scrape: "false" -datasources: - datasources.yaml: - apiVersion: 1 - datasources: - # Local prometheus instance - - access: proxy - isDefault: true - name: Prometheus - type: prometheus - url: http://prometheus-server.prometheus:9090 - # Adding a default loki as datasource because Loki is installed on some cluster (i.e: forno) for local storage of - # high-volume logs. If Loki server is not available it won't cause problems on grafana (requests to that DS won't work) - - access: proxy - name: Loki - type: loki - url: http://local-loki:3100 -deploymentStrategy: - type: Recreate -grafana.ini: - auth.google: - allow_sign_up: "true" - allowed_domains: clabs.co - auth_url: https://accounts.google.com/o/oauth2/auth - enabled: true - scopes: https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email - token_url: https://accounts.google.com/o/oauth2/token -ingress: - annotations: - kubernetes.io/tls-acme: "true" - enabled: true - path: / -persistence: - enabled: true - size: 10Gi - storageClassName: ssd -sidecar: - dashboards: - enabled: true - datasources: - enabled: false - notifiers: - enabled: false diff --git a/packages/helm-charts/leaderboard/.helmignore b/packages/helm-charts/leaderboard/.helmignore deleted file mode 100644 index 50af03172..000000000 --- a/packages/helm-charts/leaderboard/.helmignore +++ /dev/null @@ -1,22 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ diff --git a/packages/helm-charts/leaderboard/Chart.yaml b/packages/helm-charts/leaderboard/Chart.yaml deleted file mode 100644 index b605f97dc..000000000 --- a/packages/helm-charts/leaderboard/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for Kubernetes -name: leaderboard -version: 0.1.0 diff --git a/packages/helm-charts/leaderboard/templates/leaderboard.cronjob.yaml b/packages/helm-charts/leaderboard/templates/leaderboard.cronjob.yaml deleted file mode 100644 index daf3fcfa9..000000000 --- a/packages/helm-charts/leaderboard/templates/leaderboard.cronjob.yaml +++ /dev/null @@ -1,91 +0,0 @@ -apiVersion: batch/v1beta1 -kind: CronJob -metadata: - name: {{ .Release.Name }} - labels: - app: leaderboard - chart: leaderboard - release: {{ .Release.Service }} - component: leaderboard -spec: - schedule: "{{ .Values.leaderboard.schedule }}" - concurrencyPolicy: Forbid - jobTemplate: - spec: - backoffLimit: 1 - template: - spec: - containers: - - name: cloudsql-proxy - image: gcr.io/cloudsql-docker/gce-proxy:1.11 - command: - - /bin/sh - args: - - -c - - | - /cloud_sql_proxy \ - -instances={{ .Values.leaderboard.db.connection_name }}=tcp:5432 \ - -credential_file=/secrets/cloudsql/credentials.json & - CHILD_PID=$! - (while true; do if [[ -f "/tmp/pod/main-terminated" ]]; then kill $CHILD_PID; fi; sleep 1; done) & - wait $CHILD_PID - if [[ -f "/tmp/pod/main-terminated" ]]; then exit 0; fi - securityContext: - runAsUser: 2 # non-root user - allowPrivilegeEscalation: false - volumeMounts: - - name: blockscout-cloudsql-credentials - mountPath: /secrets/cloudsql - readOnly: true - - mountPath: /tmp/pod - name: tmp-pod - readOnly: true - - name: update-sheet - image: {{ .Values.leaderboard.image.repository }}:{{ .Values.leaderboard.image.tag }} - imagePullPolicy: IfNotPresent - command: - - /bin/sh - args: - - -c - - | - trap "touch /tmp/pod/main-terminated" EXIT - yarn run ts-node src/board.ts - yarn run ts-node src/upload.ts - env: - - name: LEADERBOARD_DATABASE - value: {{ .Values.leaderboard.database }} - - name: LEADERBOARD_WEB3 - value: {{ .Values.leaderboard.web3 }} - - name: LEADERBOARD_SHEET - value: {{ .Values.leaderboard.sheet }} - - name: PGUSER - valueFrom: - secretKeyRef: - name: {{ .Release.Namespace }}-leaderboard - key: DATABASE_USER - - name: PGPASSWORD - valueFrom: - secretKeyRef: - name: {{ .Release.Namespace }}-leaderboard - key: DATABASE_PASSWORD - - name: LEADERBOARD_TOKEN - valueFrom: - secretKeyRef: - name: {{ .Release.Namespace }}-leaderboard - key: LEADERBOARD_TOKEN - - name: LEADERBOARD_CREDENTIALS - valueFrom: - secretKeyRef: - name: {{ .Release.Namespace }}-leaderboard - key: LEADERBOARD_CREDENTIALS - volumeMounts: - - mountPath: /tmp/pod - name: tmp-pod - restartPolicy: Never - volumes: - - name: blockscout-cloudsql-credentials - secret: - defaultMode: 420 - secretName: blockscout-cloudsql-credentials - - name: tmp-pod - emptyDir: {} diff --git a/packages/helm-charts/leaderboard/templates/leaderboard.secret.yaml b/packages/helm-charts/leaderboard/templates/leaderboard.secret.yaml deleted file mode 100644 index d09b18422..000000000 --- a/packages/helm-charts/leaderboard/templates/leaderboard.secret.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: {{ .Release.Namespace }}-leaderboard - labels: - app: leaderboard - chart: leaderboard - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -type: Opaque -data: - DATABASE_USER: {{ .Values.leaderboard.db.username | b64enc | quote }} - DATABASE_PASSWORD: {{ .Values.leaderboard.db.password | b64enc | quote }} - LEADERBOARD_TOKEN: {{ .Values.leaderboard.token | b64enc | quote }} - LEADERBOARD_CREDENTIALS: {{ .Values.leaderboard.credentials | b64enc | quote }} diff --git a/packages/helm-charts/leaderboard/values.yaml b/packages/helm-charts/leaderboard/values.yaml deleted file mode 100644 index 0b577680e..000000000 --- a/packages/helm-charts/leaderboard/values.yaml +++ /dev/null @@ -1,17 +0,0 @@ -nodeSelector: {} - -# Expects cron schedule syntax -leaderboard: - schedule: "*/5 * * * *" - image: - repository: us.gcr.io/celo-testnet/celo-monorepo - tag: leaderboard-2708d6459b6efe2ab3ec04084d9c3819e202699f - database: blockscout - web3: https://baklava-forno.celo-testnet.org/ - sheet: - token: - credentials: - db: - username: - password: - connection_name: diff --git a/packages/helm-charts/load-test/Chart.yaml b/packages/helm-charts/load-test/Chart.yaml deleted file mode 100644 index 31b1b7efd..000000000 --- a/packages/helm-charts/load-test/Chart.yaml +++ /dev/null @@ -1,12 +0,0 @@ -name: load-test -version: 0.0.1 -description: Chart which is used to run load test -keywords: -- ethereum -- blockchain -- load-test -appVersion: v1.7.3 -dependencies: - - name: common - repository: oci://us-west1-docker.pkg.dev/devopsre/clabs-public-oci - version: 0.2.0 \ No newline at end of file diff --git a/packages/helm-charts/load-test/templates/load-test.configmap.yaml b/packages/helm-charts/load-test/templates/load-test.configmap.yaml deleted file mode 100644 index 81b2e3aa2..000000000 --- a/packages/helm-charts/load-test/templates/load-test.configmap.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ .Values.environment }}-load-test-config - labels: - app: load-test - chart: load-test - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - component: load-test -data: - static-nodes.json: {{ .Values.geth.staticNodes | b64dec | quote }} diff --git a/packages/helm-charts/load-test/templates/load-test.secret.yaml b/packages/helm-charts/load-test/templates/load-test.secret.yaml deleted file mode 100644 index 976edd2ab..000000000 --- a/packages/helm-charts/load-test/templates/load-test.secret.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: {{ .Values.environment }}-load-test - labels: - app: load-test - chart: load-test - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - component: load-test -type: Opaque -data: - accountSecret: {{ .Values.geth.accountSecret | b64enc | quote }} - mnemonic: {{ .Values.mnemonic | b64enc | quote }} diff --git a/packages/helm-charts/load-test/templates/load-test.statefulset.yaml b/packages/helm-charts/load-test/templates/load-test.statefulset.yaml deleted file mode 100644 index eeebf0da6..000000000 --- a/packages/helm-charts/load-test/templates/load-test.statefulset.yaml +++ /dev/null @@ -1,252 +0,0 @@ -{{- $reuseClient := .Values.reuse_light_clients | default false -}} -apiVersion: v1 -kind: Service -metadata: - name: load-test - labels: - component: load-test -spec: - ports: - - port: 80 - name: web - clusterIP: None - selector: - component: load-test ---- -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: {{ .Values.environment }}-load-test - labels: - app: load-test - chart: load-test - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - component: load-test -spec: - podManagementPolicy: Parallel - serviceName: load-test - replicas: {{ .Values.replicas }} - selector: - matchLabels: - app: load-test - release: {{ .Release.Name }} - component: load-test - template: - metadata: - labels: - app: load-test - release: {{ .Release.Name }} - component: load-test - spec: - initContainers: - - name: generate-keys - image: {{ .Values.celotool.image.repository }}:{{ .Values.celotool.image.tag }} - imagePullPolicy: {{ .Values.imagePullPolicy }} - args: - - | - [[ $REPLICA_NAME =~ -([0-9]+)$ ]] || exit 1 - RID=${BASH_REMATCH[1]} - echo $RID > /root/.celo/rid - celotooljs.sh generate public-key --mnemonic "$MNEMONIC" --accountType bootnode --index 0 > /root/.celo/bootnodeEnodeAddress - echo -n "Generating Bootnode enode address for the validator: " - cat /root/.celo/bootnodeEnodeAddress - - BOOTNODE_IP_ADDRESS=${{ .Release.Namespace | upper }}_BOOTNODE_SERVICE_HOST - echo `cat /root/.celo/bootnodeEnodeAddress`@$BOOTNODE_IP_ADDRESS:30301 > /root/.celo/bootnodeEnode - echo -n "Generating Bootnode enode for the validator: " - cat /root/.celo/bootnodeEnode - - celotooljs.sh generate prepare-load-test \ - --mnemonic "$MNEMONIC" \ - --threads {{ .Values.threads | default "1" }} \ - --index $RID - command: - - bash - - -c - env: - - name: REPLICA_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: MNEMONIC - valueFrom: - secretKeyRef: - name: {{ .Values.environment }}-load-test - key: mnemonic - volumeMounts: - - name: data - mountPath: /root/.celo -{{ include "common.conditional-init-genesis-container" . | indent 6 }} - - name: import-geth-account - image: {{ .Values.geth.image.repository }}:{{ .Values.geth.image.tag }} - imagePullPolicy: {{ .Values.imagePullPolicy }} - command: ["/bin/sh"] - args: - - "-c" - - | - for thread in $(seq 0 {{ sub .Values.threads 1 | default "0" }}); do - geth --nousb account import --password /root/.celo/account/accountSecret /root/.celo/pkey$thread || true - done - volumeMounts: - - name: data - mountPath: /root/.celo - - name: account - mountPath: "/root/.celo/account" - readOnly: true - containers: -{{- if $reuseClient }} - - name: geth - image: {{ $.Values.geth.image.repository }}:{{ $.Values.geth.image.tag }} - imagePullPolicy: {{ $.Values.imagePullPolicy }} - command: ["/bin/sh"] - args: - - "-c" - - |- - set -euo pipefail - cp /var/geth/static-nodes.json /root/.celo/static-nodes.json - - ACCOUNT_ADDRESSES=$(cat /root/.celo/address | tr '\n' ',') - ACCOUNT_ADDRESSES=${ACCOUNT_ADDRESSES::-1} - - ADDITIONAL_FLAGS='--allow-insecure-unlock' - -{{ include "common.geth-http-ws-flags" (dict "Values" $.Values "rpc_apis" "eth,web3,debug,admin,personal,net" "ws_port" "8545" "listen_address" "0.0.0.0") | indent 10 }} - - exec geth \ - --datadir /root/.celo \ - --ipcpath=geth.ipc \ - --nousb \ - --networkid={{ $.Values.geth.networkID }} \ - --nodekey=/root/.celo/pkey0 \ - --syncmode=fast \ - --consoleformat=json \ - --consoleoutput=stdout \ - --verbosity=1 \ - --unlock=$ACCOUNT_ADDRESSES \ - --password=/root/.celo/account/accountSecret \ - ${ADDITIONAL_FLAGS} \ - --port 30303 - resources: - requests: - memory: 4Gi - cpu: 2 - volumeMounts: - - name: data - mountPath: /root/.celo - - name: config - mountPath: /var/geth - - name: account - mountPath: "/root/.celo/account" - readOnly: true -{{- else }} -{{- range $index, $e := until (.Values.threads | int) }} - - name: geth-{{ $index }} - image: {{ $.Values.geth.image.repository }}:{{ $.Values.geth.image.tag }} - imagePullPolicy: {{ $.Values.imagePullPolicy }} - command: ["/bin/sh"] - args: - - "-c" - - |- - set -euo pipefail - cp -rp /root/.celo_share /root/.celo - cp /var/geth/static-nodes.json /root/.celo/static-nodes.json - - ACCOUNT_ADDRESS=$(awk 'NR=={{ add $index 1 }}' /root/.celo/address) - -{{ include "common.geth-http-ws-flags" (dict "Values" $.Values "rpc_apis" "eth,web3,debug,admin,personal,net" "ws_port" "8545" "listen_address" "0.0.0.0") | indent 10 }} - - exec geth \ - --nousb \ - --networkid={{ $.Values.geth.networkID }} \ - --nodekey=/root/.celo/pkey{{ $index }} \ - --syncmode=lightest \ - --consoleformat=json \ - --consoleoutput=stdout \ - --verbosity=1 \ - --unlock=$ACCOUNT_ADDRESS \ - --password=/root/.celo/account/accountSecret \ - --port {{ add 30303 $index }} \ - --http.port {{ add 8545 $index }} - resources: - requests: - memory: 200Mi - cpu: 100m - volumeMounts: - - name: data - mountPath: /root/.celo_share - readOnly: true - - name: config - mountPath: /var/geth - - name: account - mountPath: "/root/.celo_share/account" - readOnly: true -{{- end }} -{{- end }} - - name: simulate-client - image: {{ .Values.celotool.image.repository }}:{{ .Values.celotool.image.tag }} - imagePullPolicy: {{ .Values.imagePullPolicy }} - securityContext: - runAsUser: 0 - command: - - bash - - "-c" - - | - RID=`cat /root/.celo/rid` - - # Send the txs to the next load test client - RECIPIENT_INDEX=$(( ($RID + 1) % {{ .Values.replicas }} )) - - exec celotooljs.sh geth simulate-client \ -{{- if $reuseClient }} - --reuse-client \ -{{- end }} - --index $RID \ - --recipient-index $RECIPIENT_INDEX \ - --delay {{ .Values.delay }} \ - --mnemonic "$MNEMONIC" \ - --blockscout-url {{ .Values.blockscout.url }} \ - --blockscoutMeasurePercent {{ .Values.blockscout.measurePercent }} \ - --client-count {{ .Values.threads | default "1" }} - resources: - requests: - memory: 4Gi - cpu: 2 - env: - - name: LOAD_TEST_USE_RANDOM_RECIPIENT - value: "{{ default "true" .Values.use_random_recipient }}" - - name: MNEMONIC - valueFrom: - secretKeyRef: - name: {{ .Values.environment }}-load-test - key: mnemonic - - name: PASSWORD - valueFrom: - secretKeyRef: - name: {{ .Values.environment }}-load-test - key: accountSecret - - name: LOAD_TEST_USE_RANDOM_RECIPIENT - value: "true" - volumeMounts: - - name: data - mountPath: /root/.celo - volumes: - - name: data - emptyDir: {} - - name: config - configMap: - name: {{ .Values.environment }}-load-test-config - - name: account - secret: - secretName: {{ .Values.environment }}-load-test -{{- if $reuseClient }} - volumeClaimTemplates: - - metadata: - name: data - spec: - storageClassName: ssd - accessModes: [ "ReadWriteOnce" ] - resources: - requests: - storage: {{ .Values.geth.diskSize | default 10 }}Gi -{{- end }} diff --git a/packages/helm-charts/load-test/values.yaml b/packages/helm-charts/load-test/values.yaml deleted file mode 100644 index 77e40c043..000000000 --- a/packages/helm-charts/load-test/values.yaml +++ /dev/null @@ -1 +0,0 @@ -imagePullPolicy: Always diff --git a/packages/helm-charts/mock-oracle/.helmignore b/packages/helm-charts/mock-oracle/.helmignore deleted file mode 100644 index 50af03172..000000000 --- a/packages/helm-charts/mock-oracle/.helmignore +++ /dev/null @@ -1,22 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ diff --git a/packages/helm-charts/mock-oracle/Chart.yaml b/packages/helm-charts/mock-oracle/Chart.yaml deleted file mode 100644 index a12268210..000000000 --- a/packages/helm-charts/mock-oracle/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for the mock oracle -name: mock-oracle -version: 0.1.0 diff --git a/packages/helm-charts/mock-oracle/templates/oracle.cronjob.yaml b/packages/helm-charts/mock-oracle/templates/oracle.cronjob.yaml deleted file mode 100644 index f962a6dfb..000000000 --- a/packages/helm-charts/mock-oracle/templates/oracle.cronjob.yaml +++ /dev/null @@ -1,75 +0,0 @@ -apiVersion: batch/v1beta1 -kind: CronJob -metadata: - name: {{ .Release.Name }} - labels: - app: oracle - chart: oracle - release: {{ .Release.Service }} - component: oracle -spec: - schedule: "{{ .Values.oracle.cronSchedule }}" - concurrencyPolicy: Forbid - jobTemplate: - spec: - backoffLimit: 1 - template: - spec: - initContainers: - - name: get-current-price - image: {{ .Values.oracle.image.repository }}:{{ .Values.oracle.image.tag }} - imagePullPolicy: IfNotPresent - command: - - sh - - "-c" - - | - ./current_rate.sh > /celo/.celo/current_price - volumeMounts: - - name: data - mountPath: /celo/.celo - - name: get-account - image: {{ .Values.celotool.image.repository }}:{{ .Values.celotool.image.tag }} - imagePullPolicy: IfNotPresent - command: ["/bin/sh"] - args: - - "-c" - - | - celotooljs.sh generate bip32 --mnemonic "$MNEMONIC" --accountType price_oracle --index 0 > /celo/.celo/pkey - celotooljs.sh generate account-address --private-key `cat /celo/.celo/pkey` > /celo/.celo/account - volumeMounts: - - name: data - mountPath: /celo/.celo - env: - - name: MNEMONIC - valueFrom: - secretKeyRef: - name: {{ .Release.Name }} - key: MNEMONIC - containers: - - name: report-price - image: {{ .Values.celocli.image.repository }}:{{ .Values.celocli.image.tag }} - imagePullPolicy: IfNotPresent - command: ["/bin/sh"] - args: - - "-c" - - | - PRICE=`cat /celo/.celo/current_price` - echo 'current price:' - echo $PRICE - PK=`cat /celo/.celo/pkey` - ACCOUNT=`cat /celo/.celo/account` - celocli config:set --node {{ .Values.celocli.nodeUrl }} - celocli oracle:report StableToken --numerator $PRICE --privateKey $PK --from $ACCOUNT - volumeMounts: - - name: data - mountPath: /celo/.celo - env: - - name: MNEMONIC - valueFrom: - secretKeyRef: - name: {{ .Release.Name }} - key: MNEMONIC - restartPolicy: Never - volumes: - - name: data - emptyDir: {} diff --git a/packages/helm-charts/mock-oracle/templates/oracle.secret.yaml b/packages/helm-charts/mock-oracle/templates/oracle.secret.yaml deleted file mode 100644 index dac777fb2..000000000 --- a/packages/helm-charts/mock-oracle/templates/oracle.secret.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: {{ .Release.Name }} - labels: - app: oracle - chart: oracle - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -type: Opaque -data: - MNEMONIC: {{ .Values.mnemonic | b64enc | quote }} \ No newline at end of file diff --git a/packages/helm-charts/odis/Chart.yaml b/packages/helm-charts/odis/Chart.yaml deleted file mode 100644 index b0eb29da3..000000000 --- a/packages/helm-charts/odis/Chart.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: v1 -appVersion: "1.1.4" -description: A Helm chart for the ODIS app -name: odis -version: 0.1.0 -dependencies: - - name: common - repository: oci://us-west1-docker.pkg.dev/devopsre/clabs-public-oci - version: 0.2.0 \ No newline at end of file diff --git a/packages/helm-charts/odis/templates/_helpers.tpl b/packages/helm-charts/odis/templates/_helpers.tpl deleted file mode 100644 index fd37b001a..000000000 --- a/packages/helm-charts/odis/templates/_helpers.tpl +++ /dev/null @@ -1,45 +0,0 @@ -{{/* -The name of the deployment -*/}} -{{- define "name" -}} -{{- .Values.environment.cluster.name -}} -{{- end -}} - -{{/* -Common labels that are recommended to be used by Helm and Kubernetes -*/}} -{{- define "labels" -}} -app.kubernetes.io/name: {{ template "name" . }} -helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end -}} - -{{/* -Annotations to indicate to the prometheus server that this node should be scraped for metrics -*/}} -{{- define "metric-annotations" -}} -prometheus.io/scrape: "true" -prometheus.io/port: "{{ .Values.relayer.metrics.prometheusPort }}" -{{- end -}} - -{{/* -Label specific to the odis signer component -*/}} -{{- define "odis-signer-component-label" -}} -app.kubernetes.io/component: odis-signer -{{- end -}} - -{{/* -The name of the azure identity binding for the odis signer -*/}} -{{- define "azure-identity-binding-name" -}} -{{- template "name" . -}}-identity-binding -{{- end -}} - -{{/* -The name of the azure identity for the odis signer -*/}} -{{- define "azure-identity-name" -}} -{{- template "name" . -}}-identity -{{- end -}} \ No newline at end of file diff --git a/packages/helm-charts/odis/templates/azure-identity-binding.yaml b/packages/helm-charts/odis/templates/azure-identity-binding.yaml deleted file mode 100644 index 8b4f4b442..000000000 --- a/packages/helm-charts/odis/templates/azure-identity-binding.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: "aadpodidentity.k8s.io/v1" -kind: AzureIdentityBinding -metadata: - name: {{ template "azure-identity-binding-name" . }} -spec: - azureIdentity: {{ template "azure-identity-name" . }} - selector: {{ template "azure-identity-binding-name" . }} diff --git a/packages/helm-charts/odis/templates/azure-identity.yaml b/packages/helm-charts/odis/templates/azure-identity.yaml deleted file mode 100644 index 4855368bd..000000000 --- a/packages/helm-charts/odis/templates/azure-identity.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: aadpodidentity.k8s.io/v1 -kind: AzureIdentity -metadata: - name: {{ template "azure-identity-name" . }} - annotations: - aadpodidentity.k8s.io/Behavior: namespaced -spec: - type: 0 - resourceID: {{ .Values.azureKVIdentity.id }} - clientID: {{ .Values.azureKVIdentity.clientId }} diff --git a/packages/helm-charts/odis/templates/dbpassword-secret.yaml b/packages/helm-charts/odis/templates/dbpassword-secret.yaml deleted file mode 100644 index fac4d8f6c..000000000 --- a/packages/helm-charts/odis/templates/dbpassword-secret.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: db-password - labels: -{{ include "labels" . | indent 4 }} -type: Opaque -stringData: - db-password: {{ .Values.db.password }} diff --git a/packages/helm-charts/odis/templates/signer-deployment.yaml b/packages/helm-charts/odis/templates/signer-deployment.yaml deleted file mode 100644 index b6eb4dde1..000000000 --- a/packages/helm-charts/odis/templates/signer-deployment.yaml +++ /dev/null @@ -1,59 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "name" . }} - labels: -{{- include "odis-signer-component-label" . | nindent 4 }} -spec: - replicas: 1 - selector: - matchLabels: - {{- include "odis-signer-component-label" . | nindent 6 }} - template: - metadata: - labels: -{{- include "odis-signer-component-label" . | nindent 8 }} - aadpodidbinding: {{ template "azure-identity-binding-name" . }} - spec: - containers: - - name: odis-signer - securityContext: - {{- toYaml .Values.securityContext | nindent 12 }} - image: {{ .Values.image.repository }}:{{ .Values.image.tag }} - imagePullPolicy: Always - ports: - - name: http - containerPort: 3000 - command: - - bash - - "-c" - - | - sleep 60; yarn start:docker - env: - - name: SERVER_PORT - value: "3000" - - name: DB_TYPE - value: "postgres" - - name: DB_DATABASE - value: "phoneNumberPrivacy" - - name: KEYSTORE_TYPE - value: "AzureKeyVault" -{{ include "common.env-var" (dict "name" "LOG_LEVEL" "dict" .Values.log "value_name" "level") | indent 12 }} -{{ include "common.env-var" (dict "name" "LOG_FORMAT" "dict" .Values.log "value_name" "format") | indent 12 }} -{{ include "common.env-var" (dict "name" "BLOCKCHAIN_PROVIDER" "dict" .Values "value_name" "blockchainProvider") | indent 12 }} -{{ include "common.env-var" (dict "name" "BLOCKCHAIN_API_KEY" "dict" .Values "value_name" "blockchainApiKey") | indent 12 }} -{{ include "common.env-var" (dict "name" "DB_HOST" "dict" .Values.db "value_name" "host") | indent 12 }} -{{ include "common.env-var" (dict "name" "DB_PORT" "dict" .Values.db "value_name" "port") | indent 12 }} -{{ include "common.env-var" (dict "name" "DB_USERNAME" "dict" .Values.db "value_name" "username") | indent 12 }} -{{ include "common.env-var" (dict "name" "KEYSTORE_AZURE_VAULT_NAME" "dict" .Values.keystore "value_name" "vaultName") | indent 12 }} -{{ include "common.env-var" (dict "name" "PHONE_NUMBER_PRIVACY_KEY_NAME_BASE" "dict" .Values.keystore "value_name" "pnpKeyNameBase") | indent 12 }} -{{ include "common.env-var" (dict "name" "DOMAINS_KEY_NAME_BASE" "dict" .Values.keystore "value_name" "domainsKeyNameBase") | indent 12 }} -{{ include "common.env-var" (dict "name" "PHONE_NUMBER_PRIVACY_LATEST_KEY_VERSION" "dict" .Values.keystore "value_name" "pnpKeyLatestVersion") | indent 12 }} -{{ include "common.env-var" (dict "name" "DOMAINS_LATEST_KEY_VERSION" "dict" .Values.keystore "value_name" "domainsKeyLatestVersion") | indent 12 }} -{{ include "common.env-var" (dict "name" "DOMAINS_API_ENABLED" "dict" .Values.api "value_name" "domainsAPIEnabled") | indent 12 }} -{{ include "common.env-var" (dict "name" "PHONE_NUMBER_PRIVACY_API_ENABLED" "dict" .Values.api "value_name" "pnpAPIEnabled") | indent 12 }} - - name: DB_PASSWORD - valueFrom: - secretKeyRef: - name: db-password - key: db-password diff --git a/packages/helm-charts/odis/templates/signer-ingress.yaml b/packages/helm-charts/odis/templates/signer-ingress.yaml deleted file mode 100644 index b80dac8da..000000000 --- a/packages/helm-charts/odis/templates/signer-ingress.yaml +++ /dev/null @@ -1,20 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: odis-signer-ingress - annotations: - kubernetes.io/tls-acme: "true" -spec: - ingressClassName: {{ default "nginx" .Values.ingress.ingressClassName }} - tls: - - secretName: {{ .Release.Namespace }}-web-tls - rules: - - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: {{ include "name" . }} - port: - number: 3000 diff --git a/packages/helm-charts/odis/templates/signer-service.yaml b/packages/helm-charts/odis/templates/signer-service.yaml deleted file mode 100644 index 3cd4a69c4..000000000 --- a/packages/helm-charts/odis/templates/signer-service.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ include "name" . }} - labels: -{{ include "labels" . | indent 4 }} -spec: - clusterIP: None - selector: -{{ include "odis-signer-component-label" . | indent 4 }} - ports: - - name: http - port: 3000 \ No newline at end of file diff --git a/packages/helm-charts/odis/values.yaml b/packages/helm-charts/odis/values.yaml deleted file mode 100644 index 2acba1ad4..000000000 --- a/packages/helm-charts/odis/values.yaml +++ /dev/null @@ -1,80 +0,0 @@ -# Default values for odis. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -replicaCount: 1 - -image: - repository: nginx - pullPolicy: IfNotPresent - # Overrides the image tag whose default is the chart appVersion. - tag: "" - -imagePullSecrets: [] -nameOverride: "" -fullnameOverride: "" - -serviceAccount: - # Specifies whether a service account should be created - create: true - # Annotations to add to the service account - annotations: {} - # The name of the service account to use. - # If not set and create is true, a name is generated using the fullname template - name: "" - -podAnnotations: {} - -podSecurityContext: {} - # fsGroup: 2000 - -securityContext: {} - # capabilities: - # drop: - # - ALL - # readOnlyRootFilesystem: true - # runAsNonRoot: true - # runAsUser: 1000 - -service: - type: ClusterIP - port: 80 - -ingress: - enabled: false - ingressClassName: nginx - annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - hosts: - - host: chart-example.local - paths: [] - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local - -resources: {} - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - # limits: - # cpu: 100m - # memory: 128Mi - # requests: - # cpu: 100m - # memory: 128Mi - -autoscaling: - enabled: false - minReplicas: 1 - maxReplicas: 100 - targetCPUUtilizationPercentage: 80 - # targetMemoryUtilizationPercentage: 80 - -nodeSelector: {} - -tolerations: [] - -affinity: {} diff --git a/packages/helm-charts/oracle-rbac/Chart.yaml b/packages/helm-charts/oracle-rbac/Chart.yaml deleted file mode 100644 index 4f10fc0d1..000000000 --- a/packages/helm-charts/oracle-rbac/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: '1.0' -description: A Helm chart to get the RBAC token needed by the oracle to reach the K8s API server -name: oracle-rbac -version: 0.3.0 diff --git a/packages/helm-charts/oracle-rbac/templates/_helper.tpl b/packages/helm-charts/oracle-rbac/templates/_helper.tpl deleted file mode 100644 index 75e25d060..000000000 --- a/packages/helm-charts/oracle-rbac/templates/_helper.tpl +++ /dev/null @@ -1,11 +0,0 @@ -{{- define "name" -}} -{{- .Values.environment.name -}}-{{- .Values.environment.currencyPair | lower -}}-oracle-rbac-{{- .index -}} -{{- end -}} - -{{- define "secret-name" -}} -{{- .Values.environment.name -}}-{{- .Values.environment.currencyPair | lower -}}-oracle-rbac-secret-{{- .index -}} -{{- end -}} - -{{- define "oracle-pod-name" -}} -{{- .Values.environment.name -}}-{{- .Values.environment.currencyPair | lower -}}-oracle-{{- .index -}} -{{- end -}} diff --git a/packages/helm-charts/oracle-rbac/templates/role.yaml b/packages/helm-charts/oracle-rbac/templates/role.yaml deleted file mode 100644 index f5ede1a1b..000000000 --- a/packages/helm-charts/oracle-rbac/templates/role.yaml +++ /dev/null @@ -1,13 +0,0 @@ -{{ range $index, $e := until (.Values.oracle.replicas | int) }} -{{- $index_counter := (dict "Values" $.Values "index" $index) -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: {{ template "name" $index_counter }} -rules: -- apiGroups: [""] - resources: ["pods"] - resourceNames: ["{{ template "oracle-pod-name" $index_counter }}"] - verbs: ["get", "patch"] ---- -{{ end }} diff --git a/packages/helm-charts/oracle-rbac/templates/rolebinding.yaml b/packages/helm-charts/oracle-rbac/templates/rolebinding.yaml deleted file mode 100644 index 787908aaa..000000000 --- a/packages/helm-charts/oracle-rbac/templates/rolebinding.yaml +++ /dev/null @@ -1,15 +0,0 @@ -{{ range $index, $e := until (.Values.oracle.replicas | int) }} -{{- $index_counter := (dict "Values" $.Values "index" $index) -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: {{ template "name" $index_counter }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: {{ template "name" $index_counter }} -subjects: -- kind: ServiceAccount - name: {{ template "name" $index_counter }} ---- -{{ end }} diff --git a/packages/helm-charts/oracle-rbac/templates/secret.yaml b/packages/helm-charts/oracle-rbac/templates/secret.yaml deleted file mode 100644 index b2bbda2cb..000000000 --- a/packages/helm-charts/oracle-rbac/templates/secret.yaml +++ /dev/null @@ -1,11 +0,0 @@ -{{ range $index, $e := until (.Values.oracle.replicas | int) }} -{{- $index_counter := (dict "Values" $.Values "index" $index) -}} -apiVersion: v1 -kind: Secret -type: kubernetes.io/service-account-token -metadata: - name: {{ template "secret-name" $index_counter }} - annotations: - kubernetes.io/service-account.name: {{ template "name" $index_counter }} ---- -{{ end }} diff --git a/packages/helm-charts/oracle-rbac/templates/service-account.yaml b/packages/helm-charts/oracle-rbac/templates/service-account.yaml deleted file mode 100644 index 004c02467..000000000 --- a/packages/helm-charts/oracle-rbac/templates/service-account.yaml +++ /dev/null @@ -1,8 +0,0 @@ -{{ range $index, $e := until (.Values.oracle.replicas | int) }} -{{- $index_counter := (dict "Values" $.Values "index" $index) -}} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ template "name" $index_counter}} ---- -{{ end }} diff --git a/packages/helm-charts/oracle-rbac/values.yaml b/packages/helm-charts/oracle-rbac/values.yaml deleted file mode 100644 index a7e48cd12..000000000 --- a/packages/helm-charts/oracle-rbac/values.yaml +++ /dev/null @@ -1,6 +0,0 @@ -environment: - name: default - currencyPair: CELOUSD - -oracle: - replicas: 1 diff --git a/packages/helm-charts/oracle/CELOBRL.yaml b/packages/helm-charts/oracle/CELOBRL.yaml deleted file mode 100644 index 21d64348f..000000000 --- a/packages/helm-charts/oracle/CELOBRL.yaml +++ /dev/null @@ -1,53 +0,0 @@ -oracle: - currencyPair: CELOBRL - aggregation: - mid: - maxExchangeVolumeShare: 1 - maxPercentageDeviation: 0.025 - maxPercentageBidAskSpread: 0.015 - metrics: - enabled: true - prometheusPort: 9090 - apiRequestTimeoutMs: 5000 - circuitBreakerPriceChangeThreshold: 0.25 - gasPriceMultiplier: 1.5 - priceSources: "[ - [ - { exchange: 'BINANCE', symbol: 'CELOBUSD', toInvert: false }, - { exchange: 'BINANCE', symbol: 'BUSDBRL', toInvert: false } - ], - [ - { exchange: 'BINANCE', symbol: 'CELOUSDT', toInvert: false }, - { exchange: 'BINANCE', symbol: 'USDTBRL', toInvert: false } - ], - [ - { exchange: 'BINANCE', symbol: 'CELOBTC', toInvert: false }, - { exchange: 'MERCADO', symbol: 'BTCBRL', toInvert: false } - ], - [ - { exchange: 'BINANCEUS', symbol: 'CELOUSD', toInvert: false }, - { exchange: 'BITSO', symbol: 'USDBRL', toInvert: false } - ], - [ - { exchange: 'COINBASE', symbol: 'CELOUSD', toInvert: false}, - { exchange: 'BITSO', symbol: 'USDBRL', toInvert: false } - ], - [ - { exchange: 'COINBASE', symbol: 'CELOBTC', toInvert: false }, - { exchange: 'NOVADAX', symbol: 'BTCBRL', toInvert: false } - ], - [ - { exchange: 'OKX', symbol: 'CELOUSDT', toInvert: false }, - { exchange: 'OKX', symbol: 'BTCUSDT', toInvert: true }, - { exchange: 'NOVADAX', symbol: 'BTCBRL', toInvert: false } - ], - [ - {exchange: 'KUCOIN', symbol: 'CELOUSDT', toInvert: false}, - { exchange: 'BITSO', symbol: 'USDTBRL', toInvert: false } - ] - ]" - minPriceSourceCount: 2 - reportStrategy: BLOCK_BASED - reporter: - blockBased: - minReportPriceChangeThreshold: 0.005 diff --git a/packages/helm-charts/oracle/CELOEUR.yaml b/packages/helm-charts/oracle/CELOEUR.yaml deleted file mode 100644 index ec0ac1b9e..000000000 --- a/packages/helm-charts/oracle/CELOEUR.yaml +++ /dev/null @@ -1,47 +0,0 @@ -oracle: - currencyPair: CELOEUR - aggregation: - mid: - maxExchangeVolumeShare: 1 - maxPercentageDeviation: 0.025 - maxPercentageBidAskSpread: 0.015 - metrics: - enabled: true - prometheusPort: 9090 - apiRequestTimeoutMs: 5000 - circuitBreakerPriceChangeThreshold: 0.25 - gasPriceMultiplier: 1.5 - priceSources: "[ - [ - {exchange: 'COINBASE', symbol: 'CELOEUR', toInvert: false}], - [ - {exchange: 'COINBASE', symbol: 'CELOUSD', toInvert: false}, - {exchange: 'COINBASE', symbol: 'USDTUSD', toInvert: true}, - {exchange: 'COINBASE', symbol: 'USDTEUR', toInvert: false} - ], - [ - {exchange: 'COINBASE', symbol: 'CELOBTC', toInvert: false}, - {exchange: 'COINBASE', symbol: 'BTCEUR', toInvert: false} - ], - [ - {exchange: 'BINANCE', symbol: 'CELOUSDT', toInvert: false}, - {exchange: 'BINANCE', symbol: 'EURUSDT', toInvert: true} - ], - [ - {exchange: 'BINANCE', symbol: 'CELOBTC', toInvert: false}, - {exchange: 'BINANCE', symbol: 'BTCEUR', toInvert: false} - ], - [ - {exchange: 'OKX', symbol: 'CELOUSDT', toInvert: false}, - {exchange: 'COINBASE', symbol: 'USDTEUR', toInvert: false} - ], - [ - {exchange: 'KUCOIN', symbol: 'CELOUSDT', toInvert: false}, - {exchange: 'KRAKEN', symbol: 'USDTEUR', toInvert: false} - ], - ]" - minPriceSourceCount: 2 - reportStrategy: BLOCK_BASED - reporter: - blockBased: - minReportPriceChangeThreshold: 0.005 diff --git a/packages/helm-charts/oracle/CELOUSD.yaml b/packages/helm-charts/oracle/CELOUSD.yaml deleted file mode 100644 index c57e8bb17..000000000 --- a/packages/helm-charts/oracle/CELOUSD.yaml +++ /dev/null @@ -1,46 +0,0 @@ -oracle: - currencyPair: CELOUSD - aggregation: - mid: - maxExchangeVolumeShare: 1 - maxPercentageDeviation: 0.025 - maxPercentageBidAskSpread: 0.015 - metrics: - enabled: true - prometheusPort: 9090 - apiRequestTimeoutMs: 5000 - circuitBreakerPriceChangeThreshold: 0.25 - gasPriceMultiplier: 1.5 - priceSources: "[ - [ - {exchange: 'COINBASE', symbol: 'CELOUSD', toInvert: false} - ], - [ - {exchange: 'COINBASE', symbol: 'CELOBTC', toInvert: false}, - {exchange: 'COINBASE', symbol: 'BTCUSD', toInvert: false} - ], - [ - {exchange: 'BINANCE', symbol: 'CELOBUSD', toInvert: false}, - {exchange: 'COINBASE', symbol: 'BUSDUSD', toInvert: false} - ], - [ - {exchange: 'BINANCE', symbol: 'CELOUSDT', toInvert: false}, - {exchange: 'KRAKEN', symbol: 'USDTUSD', toInvert: false} - ], - [ - {exchange: 'BINANCEUS', symbol: 'CELOUSD', toInvert: false } - ], - [ - {exchange: 'OKX', symbol: 'CELOUSDT', toInvert: false}, - {exchange: 'COINBASE', symbol: 'USDTUSD', toInvert: false} - ], - [ - {exchange: 'KUCOIN', symbol: 'CELOUSDT', toInvert: false}, - {exchange: 'KRAKEN', symbol: 'USDTUSD', toInvert: false} - ], - ]" - minPriceSourceCount: 2 - reportStrategy: BLOCK_BASED - reporter: - blockBased: - minReportPriceChangeThreshold: 0.005 diff --git a/packages/helm-charts/oracle/CELOXOF.yaml b/packages/helm-charts/oracle/CELOXOF.yaml deleted file mode 100644 index e719e9902..000000000 --- a/packages/helm-charts/oracle/CELOXOF.yaml +++ /dev/null @@ -1,109 +0,0 @@ -oracle: - currencyPair: CELOXOF - overrideOracleCount: 12 # At 5s block time, every client reports once per minute - aggregation: - mid: - maxExchangeVolumeShare: 1 - maxPercentageDeviation: 0.025 - maxPercentageBidAskSpread: 0.015 - metrics: - enabled: true - prometheusPort: 9090 - apiRequestTimeoutMs: 5000 - circuitBreakerPriceChangeThreshold: 0.25 - gasPriceMultiplier: 1.5 - priceSources: "[ - [ - {exchange: 'BINANCE', symbol: 'CELOUSDT', toInvert: false}, - {exchange: 'BINANCE', symbol: 'EURUSDT', toInvert: true}, - {exchange: 'ALPHAVANTAGE', symbol: 'EURXOF', toInvert: false, ignoreVolume: true} - ], - [ - {exchange: 'BINANCE', symbol: 'CELOUSDT', toInvert: false}, - {exchange: 'BINANCE', symbol: 'EURUSDT', toInvert: true}, - {exchange: 'CURRENCYAPI', symbol: 'EURXOF', toInvert: false, ignoreVolume: true} - ], - [ - {exchange: 'BINANCE', symbol: 'CELOUSDT', toInvert: false}, - {exchange: 'BINANCE', symbol: 'EURUSDT', toInvert: true}, - {exchange: 'XIGNITE', symbol: 'EURXOF', toInvert: false, ignoreVolume: true} - ], - - [ - {exchange: 'COINBASE', symbol: 'CELOUSD', toInvert: false}, - {exchange: 'COINBASE', symbol: 'USDTUSD', toInvert: true}, - {exchange: 'COINBASE', symbol: 'USDTEUR', toInvert: false}, - {exchange: 'ALPHAVANTAGE', symbol: 'EURXOF', toInvert: false, ignoreVolume: true} - ], - [ - {exchange: 'COINBASE', symbol: 'CELOUSD', toInvert: false}, - {exchange: 'COINBASE', symbol: 'USDTUSD', toInvert: true}, - {exchange: 'COINBASE', symbol: 'USDTEUR', toInvert: false}, - {exchange: 'CURRENCYAPI', symbol: 'EURXOF', toInvert: false, ignoreVolume: true} - ], - [ - {exchange: 'COINBASE', symbol: 'CELOUSD', toInvert: false}, - {exchange: 'COINBASE', symbol: 'USDTUSD', toInvert: true}, - {exchange: 'COINBASE', symbol: 'USDTEUR', toInvert: false}, - {exchange: 'XIGNITE', symbol: 'EURXOF', toInvert: false, ignoreVolume: true} - ], - - [ - {exchange: 'OKX', symbol: 'CELOUSDT', toInvert: false}, - {exchange: 'BITSTAMP', symbol: 'USDTEUR', toInvert: false}, - {exchange: 'ALPHAVANTAGE', symbol: 'EURXOF', toInvert: false, ignoreVolume: true} - ], - [ - {exchange: 'OKX', symbol: 'CELOUSDT', toInvert: false}, - {exchange: 'BITSTAMP', symbol: 'USDTEUR', toInvert: false}, - {exchange: 'CURRENCYAPI', symbol: 'EURXOF', toInvert: false, ignoreVolume: true} - ], - [ - {exchange: 'OKX', symbol: 'CELOUSDT', toInvert: false}, - {exchange: 'BITSTAMP', symbol: 'USDTEUR', toInvert: false}, - {exchange: 'XIGNITE', symbol: 'EURXOF', toInvert: false, ignoreVolume: true} - ], - - [ - {exchange: 'KUCOIN', symbol: 'CELOUSDT', toInvert: false}, - {exchange: 'KRAKEN', symbol: 'USDTEUR', toInvert: false}, - {exchange: 'ALPHAVANTAGE', symbol: 'EURXOF', toInvert: false, ignoreVolume: true} - ], - [ - {exchange: 'KUCOIN', symbol: 'CELOUSDT', toInvert: false}, - {exchange: 'KRAKEN', symbol: 'USDTEUR', toInvert: false}, - {exchange: 'CURRENCYAPI', symbol: 'EURXOF', toInvert: false, ignoreVolume: true} - ], - [ - {exchange: 'KUCOIN', symbol: 'CELOUSDT', toInvert: false}, - {exchange: 'KRAKEN', symbol: 'USDTEUR', toInvert: false}, - {exchange: 'XIGNITE', symbol: 'EURXOF', toInvert: false, ignoreVolume: true} - ], - - [ - {exchange: 'BITGET', symbol: 'CELOUSDT', toInvert: false}, - {exchange: 'BITGET', symbol: 'USDTEUR', toInvert: false}, - {exchange: 'ALPHAVANTAGE', symbol: 'EURXOF', toInvert: false, ignoreVolume: true} - ], - [ - {exchange: 'BITGET', symbol: 'CELOUSDT', toInvert: false}, - {exchange: 'BITGET', symbol: 'USDTEUR', toInvert: false}, - {exchange: 'CURRENCYAPI', symbol: 'EURXOF', toInvert: false, ignoreVolume: true} - ], - [ - {exchange: 'BITGET', symbol: 'CELOUSDT', toInvert: false}, - {exchange: 'BITGET', symbol: 'USDTEUR', toInvert: false}, - {exchange: 'XIGNITE', symbol: 'EURXOF', toInvert: false, ignoreVolume: true} - ] - ]" - # Additional sources missing adapters [ - # {exchange: 'UPBIT', symbol: 'CELOKRW', toInvert: false}, - # {exchange: 'UPBIT', symbol: 'BTCKRW', toInvert: true}, - # {exchange: 'KRAKEN', symbol: 'BTCEUR', toInvert: false}, - # {exchange: 'ALPHAVANTAGE', symbol: 'EURXOF', toInvert: false, ignoreVolume: true} - # ] - minPriceSourceCount: 9 - reportStrategy: BLOCK_BASED - reporter: - blockBased: - minReportPriceChangeThreshold: 0.005 diff --git a/packages/helm-charts/oracle/Chart.yaml b/packages/helm-charts/oracle/Chart.yaml deleted file mode 100644 index 01ca063f2..000000000 --- a/packages/helm-charts/oracle/Chart.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: v1 -appVersion: '1.0' -description: A Helm chart for the oracle client -name: oracle -version: 0.2.1 -dependencies: - - name: common - repository: oci://us-west1-docker.pkg.dev/devopsre/clabs-public-oci - version: 0.2.0 diff --git a/packages/helm-charts/oracle/EUROCEUR.yaml b/packages/helm-charts/oracle/EUROCEUR.yaml deleted file mode 100644 index ee365067a..000000000 --- a/packages/helm-charts/oracle/EUROCEUR.yaml +++ /dev/null @@ -1,31 +0,0 @@ -oracle: - currencyPair: EUROCEUR - aggregation: - mid: - maxExchangeVolumeShare: 1 - maxPercentageDeviation: 0.01 - maxPercentageBidAskSpread: 0.005 - metrics: - enabled: true - prometheusPort: 9090 - apiRequestTimeoutMs: 5000 - circuitBreakerPriceChangeThreshold: 0.25 - gasPriceMultiplier: 1.5 - priceSources: "[ - [ - {exchange: 'COINBASE', symbol: 'EUROCEUR', toInvert: false} - ], - [ - {exchange: 'COINBASE', symbol: 'EUROCUSD', toInvert: false}, - {exchange: 'COINBASE', symbol: 'USDTUSD', toInvert: true}, - {exchange: 'COINBASE', symbol: 'USDTEUR', toInvert: false} - ], - [ - {exchange: 'BITSTAMP', symbol: 'EUROCEUR', toInvert: false}, - ] - ]" - minPriceSourceCount: 2 - reportStrategy: BLOCK_BASED - reporter: - blockBased: - minReportPriceChangeThreshold: 0.0005 # 0.05% diff --git a/packages/helm-charts/oracle/EUROCXOF.yaml b/packages/helm-charts/oracle/EUROCXOF.yaml deleted file mode 100644 index ca09ed043..000000000 --- a/packages/helm-charts/oracle/EUROCXOF.yaml +++ /dev/null @@ -1,65 +0,0 @@ -oracle: - currencyPair: EUROCXOF - overrideOracleCount: 12 # At 5s block time, every client reports once per minute - aggregation: - mid: - maxExchangeVolumeShare: 1 - maxPercentageDeviation: 0.01 - maxPercentageBidAskSpread: 0.005 - metrics: - enabled: true - prometheusPort: 9090 - apiRequestTimeoutMs: 5000 - circuitBreakerPriceChangeThreshold: 0.25 - gasPriceMultiplier: 1.5 - priceSources: "[ - [ - {exchange: 'COINBASE', symbol: 'EUROCEUR', toInvert: false}, - {exchange: 'ALPHAVANTAGE', symbol: 'EURXOF', toInvert: false, ignoreVolume: true} - ], - [ - {exchange: 'COINBASE', symbol: 'EUROCEUR', toInvert: false}, - {exchange: 'CURRENCYAPI', symbol: 'EURXOF', toInvert: false, ignoreVolume: true} - ], - [ - {exchange: 'COINBASE', symbol: 'EUROCEUR', toInvert: false}, - {exchange: 'XIGNITE', symbol: 'EURXOF', toInvert: false, ignoreVolume: true} - ], - - [ - {exchange: 'COINBASE', symbol: 'EUROCUSD', toInvert: false}, - {exchange: 'COINBASE', symbol: 'USDTUSD', toInvert: true}, - {exchange: 'COINBASE', symbol: 'USDTEUR', toInvert: false}, - {exchange: 'ALPHAVANTAGE', symbol: 'EURXOF', toInvert: false, ignoreVolume: true} - ], - [ - {exchange: 'COINBASE', symbol: 'EUROCUSD', toInvert: false}, - {exchange: 'COINBASE', symbol: 'USDTUSD', toInvert: true}, - {exchange: 'COINBASE', symbol: 'USDTEUR', toInvert: false}, - {exchange: 'CURRENCYAPI', symbol: 'EURXOF', toInvert: false, ignoreVolume: true} - ], - [ - {exchange: 'COINBASE', symbol: 'EUROCUSD', toInvert: false}, - {exchange: 'COINBASE', symbol: 'USDTUSD', toInvert: true}, - {exchange: 'COINBASE', symbol: 'USDTEUR', toInvert: false}, - {exchange: 'XIGNITE', symbol: 'EURXOF', toInvert: false, ignoreVolume: true} - ], - - [ - {exchange: 'BITSTAMP', symbol: 'EUROCEUR', toInvert: false}, - {exchange: 'ALPHAVANTAGE', symbol: 'EURXOF', toInvert: false, ignoreVolume: true} - ], - [ - {exchange: 'BITSTAMP', symbol: 'EUROCEUR', toInvert: false}, - {exchange: 'CURRENCYAPI', symbol: 'EURXOF', toInvert: false, ignoreVolume: true} - ], - [ - {exchange: 'BITSTAMP', symbol: 'EUROCEUR', toInvert: false}, - {exchange: 'XIGNITE', symbol: 'EURXOF', toInvert: false, ignoreVolume: true} - ] - ]" - minPriceSourceCount: 6 - reportStrategy: BLOCK_BASED - reporter: - blockBased: - minReportPriceChangeThreshold: 0.0005 # 0.05% diff --git a/packages/helm-charts/oracle/EURXOF.yaml b/packages/helm-charts/oracle/EURXOF.yaml deleted file mode 100644 index 6a4e9367f..000000000 --- a/packages/helm-charts/oracle/EURXOF.yaml +++ /dev/null @@ -1,30 +0,0 @@ -oracle: - currencyPair: EURXOF - overrideOracleCount: 12 # At 5s block time, every client reports once per minute - aggregation: - mid: - maxExchangeVolumeShare: 1 - maxPercentageDeviation: 0.01 - maxPercentageBidAskSpread: 0.005 - metrics: - enabled: true - prometheusPort: 9090 - apiRequestTimeoutMs: 5000 - circuitBreakerPriceChangeThreshold: 0.25 - gasPriceMultiplier: 1.5 - priceSources: "[ - [ - {exchange: 'ALPHAVANTAGE', symbol: 'EURXOF', toInvert: false} - ], - [ - {exchange: 'CURRENCYAPI', symbol: 'EURXOF', toInvert: false} - ], - [ - {exchange: 'XIGNITE', symbol: 'EURXOF', toInvert: false} - ] - ]" - minPriceSourceCount: 3 - reportStrategy: BLOCK_BASED - reporter: - blockBased: - minReportPriceChangeThreshold: 0.0005 # 0.05% diff --git a/packages/helm-charts/oracle/USDCBRL.yaml b/packages/helm-charts/oracle/USDCBRL.yaml deleted file mode 100644 index 94080e764..000000000 --- a/packages/helm-charts/oracle/USDCBRL.yaml +++ /dev/null @@ -1,47 +0,0 @@ -oracle: - currencyPair: USDCBRL - aggregation: - mid: - maxExchangeVolumeShare: 1 - maxPercentageDeviation: 0.01 - maxPercentageBidAskSpread: 0.005 - metrics: - enabled: true - prometheusPort: 9090 - apiRequestTimeoutMs: 5000 - circuitBreakerPriceChangeThreshold: 0.25 - gasPriceMultiplier: 1.5 - priceSources: "[ - [ - { exchange: 'MERCADO', symbol: 'USDCBRL', toInvert: false } - ], - [ - {exchange: 'KRAKEN', symbol: 'USDCUSD', toInvert: false}, - {exchange: 'BITSO', symbol: 'USDBRL', toInvert: false } - ], - [ - {exchange: 'COINBASE', symbol: 'USDTUSDC', toInvert: true}, - {exchange: 'BINANCE', symbol: 'USDTBRL', toInvert: false } - ], - [ - {exchange: 'WHITEBIT', symbol: 'USDCUSDT', toInvert: false}, - {exchange: 'BINANCE', symbol: 'USDTBRL', toInvert: false } - ], - [ - {exchange: 'KRAKEN', symbol: 'BTCUSDC', toInvert: true}, - {exchange: 'BINANCE', symbol: 'BTCBRL', toInvert: false } - ], - [ - {exchange: 'COINBASE', symbol: 'USDTUSDC', toInvert: true}, - {exchange: 'BITGET', symbol: 'USDTBRL', toInvert: false } - ], - [ - {exchange: 'WHITEBIT', symbol: 'USDCUSDT', toInvert: false}, - {exchange: 'BITGET', symbol: 'USDTBRL', toInvert: false } - ], - ]" - minPriceSourceCount: 2 - reportStrategy: BLOCK_BASED - reporter: - blockBased: - minReportPriceChangeThreshold: 0.0005 # 0.05% diff --git a/packages/helm-charts/oracle/USDCEUR.yaml b/packages/helm-charts/oracle/USDCEUR.yaml deleted file mode 100644 index 112008c9e..000000000 --- a/packages/helm-charts/oracle/USDCEUR.yaml +++ /dev/null @@ -1,35 +0,0 @@ -oracle: - currencyPair: USDCEUR - aggregation: - mid: - maxExchangeVolumeShare: 1 - maxPercentageDeviation: 0.01 - maxPercentageBidAskSpread: 0.005 - metrics: - enabled: true - prometheusPort: 9090 - apiRequestTimeoutMs: 5000 - circuitBreakerPriceChangeThreshold: 0.25 - gasPriceMultiplier: 1.5 - priceSources: "[ - [ - {exchange: 'KRAKEN', symbol: 'USDCEUR', toInvert: false} - ], - [ - {exchange: 'COINBASE', symbol: 'USDTUSDC', toInvert: true}, - {exchange: 'COINBASE', symbol: 'USDTEUR', toInvert: false} - ], - [ - {exchange: 'WHITEBIT', symbol: 'USDCUSDT', toInvert: false}, - {exchange: 'COINBASE', symbol: 'USDTEUR', toInvert: false} - ], - [ - {exchange: 'KRAKEN', symbol: 'USDCUSD', toInvert: false}, - {exchange: 'KRAKEN', symbol: 'EURUSD', toInvert: true} - ], - ]" - minPriceSourceCount: 2 - reportStrategy: BLOCK_BASED - reporter: - blockBased: - minReportPriceChangeThreshold: 0.0005 # 0.05% diff --git a/packages/helm-charts/oracle/USDCUSD.yaml b/packages/helm-charts/oracle/USDCUSD.yaml deleted file mode 100644 index bdf4cdfa3..000000000 --- a/packages/helm-charts/oracle/USDCUSD.yaml +++ /dev/null @@ -1,51 +0,0 @@ -oracle: - currencyPair: USDCUSD - aggregation: - mid: - maxExchangeVolumeShare: 1 - maxPercentageDeviation: 0.005 - maxPercentageBidAskSpread: 0.005 - metrics: - enabled: true - prometheusPort: 9090 - apiRequestTimeoutMs: 5000 - circuitBreakerPriceChangeThreshold: 0.25 - gasPriceMultiplier: 1.5 - priceSources: "[ - [ - {exchange: 'BINANCE', symbol: 'USDCUSDT', toInvert: false}, - {exchange: 'KRAKEN', symbol: 'USDTUSD', toInvert: false } - ], - [ - {exchange: 'KRAKEN', symbol: 'USDCUSD', toInvert: false} - ], - [ - {exchange: 'BITSTAMP', symbol: 'USDCUSD', toInvert: false} - ], - [ - {exchange: 'COINBASE', symbol: 'USDTUSDC', toInvert: true}, - {exchange: 'COINBASE', symbol: 'USDTUSD', toInvert: false} - ], - [ - {exchange: 'OKX', symbol: 'USDCUSDT', toInvert: false}, - {exchange: 'BITSTAMP', symbol: 'USDTUSD', toInvert: false} - ], - [ - {exchange: 'BITGET', symbol: 'USDTUSDC', toInvert: true}, - {exchange: 'KRAKEN', symbol: 'USDTUSD', toInvert: false} - ], - [ - {exchange: 'KUCOIN', symbol: 'USDCUSDT', toInvert: false}, - {exchange: 'COINBASE', symbol: 'USDTUSD', toInvert: false} - ] - ]" - # Additional sources missing adapters - # [ - # {exchange: 'Bybit', symbol: 'USDTUSDC', toInvert: true}, - # {exchange: 'Kraken', symbol: 'USDTUSD', toInvert: false} - # ], - minPriceSourceCount: 5 - reportStrategy: BLOCK_BASED - reporter: - blockBased: - minReportPriceChangeThreshold: 0.0005 # 0.05% diff --git a/packages/helm-charts/oracle/templates/_helper.tpl b/packages/helm-charts/oracle/templates/_helper.tpl deleted file mode 100644 index ece6db7db..000000000 --- a/packages/helm-charts/oracle/templates/_helper.tpl +++ /dev/null @@ -1,55 +0,0 @@ -{{/* -The name of the deployment -*/}} -{{- define "name" -}} -{{- .Values.environment.name -}}-{{- .Values.oracle.currencyPair | lower -}}-oracle -{{- end -}} - -{{/* -Common labels that are recommended to be used by Helm and Kubernetes -*/}} -{{- define "labels" -}} -app.kubernetes.io/name: {{ template "name" . }} -helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end -}} - -{{/* -Annotations to indicate to the prometheus server that this node should be scraped for metrics -*/}} -{{- define "metric-annotations" -}} -prometheus.io/scrape: "true" -prometheus.io/port: "{{ .Values.oracle.metrics.prometheusPort }}" -{{- end -}} - -{{/* -Label specific to the oracle client component -*/}} -{{- define "oracle-client-component-label" -}} -app.kubernetes.io/component: oracle-client -{{- end -}} - -{{/* -The name of the azure identity binding for all oracles -*/}} -{{- define "azure-identity-binding-name" -}} -{{- with .dot -}}{{ template "name" . }}{{- end -}}-{{ .index }}-identity-binding -{{- end -}} - -{{/* -The name of the azure identity for all oracles -*/}} -{{- define "azure-identity-name" -}} -{{- with .dot -}}{{ template "name" . }}{{- end -}}-{{ .index }}-identity -{{- end -}} - -{{/* -The name of the pkey secret -*/}} -{{- define "pkey-secret-name" -}} -pkey-secret-{{- .Values.oracle.currencyPair | lower -}} -{{- end -}} -{{- define "api-keys-secret-name" -}} -api-keys-{{- .Values.oracle.currencyPair | lower -}} -{{- end -}} diff --git a/packages/helm-charts/oracle/templates/api-keys-secret.yaml b/packages/helm-charts/oracle/templates/api-keys-secret.yaml deleted file mode 100644 index db2d40d78..000000000 --- a/packages/helm-charts/oracle/templates/api-keys-secret.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: {{ template "api-keys-secret-name" . }} - labels: -{{ include "labels" . | indent 4 }} -type: Opaque -data: - api_keys: {{ .Values.oracle.api_keys | b64enc }} diff --git a/packages/helm-charts/oracle/templates/azure-identity-binding.yaml b/packages/helm-charts/oracle/templates/azure-identity-binding.yaml deleted file mode 100644 index 14d73a9da..000000000 --- a/packages/helm-charts/oracle/templates/azure-identity-binding.yaml +++ /dev/null @@ -1,12 +0,0 @@ -{{- range $index, $identity := .Values.oracle.identities -}} -{{ if (hasKey $identity "azure") }} -apiVersion: "aadpodidentity.k8s.io/v1" -kind: AzureIdentityBinding -metadata: - name: {{ template "azure-identity-binding-name" (dict "dot" $ "index" $index) }} -spec: - azureIdentity: {{ template "azure-identity-name" (dict "dot" $ "index" $index) }} - selector: {{ template "azure-identity-binding-name" (dict "dot" $ "index" $index) }} ---- -{{ end }} -{{ end }} diff --git a/packages/helm-charts/oracle/templates/azure-identity.yaml b/packages/helm-charts/oracle/templates/azure-identity.yaml deleted file mode 100644 index 1ed705377..000000000 --- a/packages/helm-charts/oracle/templates/azure-identity.yaml +++ /dev/null @@ -1,15 +0,0 @@ -{{- range $index, $identity := .Values.oracle.identities -}} -{{ if (hasKey $identity "azure") }} -apiVersion: aadpodidentity.k8s.io/v1 -kind: AzureIdentity -metadata: - name: {{ template "azure-identity-name" (dict "dot" $ "index" $index) }} - annotations: - aadpodidentity.k8s.io/Behavior: namespaced -spec: - type: 0 - resourceID: {{ $identity.azure.id }} - clientID: {{ $identity.azure.clientId }} ---- -{{ end }} -{{ end }} diff --git a/packages/helm-charts/oracle/templates/pkey-secret.yaml b/packages/helm-charts/oracle/templates/pkey-secret.yaml deleted file mode 100644 index 6436ee7bb..000000000 --- a/packages/helm-charts/oracle/templates/pkey-secret.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: {{ template "pkey-secret-name" . }} - labels: -{{ include "labels" . | indent 4 }} -type: Opaque -data: -{{ range $index, $identity := .Values.oracle.identities }} -{{ if (hasKey $identity "privateKey") }} - private-key-{{ $index }}: {{ $identity.privateKey | b64enc }} -{{ end }} -{{ end }} diff --git a/packages/helm-charts/oracle/templates/statefulset.yaml b/packages/helm-charts/oracle/templates/statefulset.yaml deleted file mode 100644 index 423881c0e..000000000 --- a/packages/helm-charts/oracle/templates/statefulset.yaml +++ /dev/null @@ -1,163 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ template "name" . }} - labels: -{{ include "labels" . | indent 4 }} -{{ include "oracle-client-component-label" . | indent 4 }} -spec: - clusterIP: None - selector: -{{ include "oracle-client-component-label" . | indent 4 }} ---- -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: {{ template "name" . }} - labels: -{{ include "labels" . | indent 4 }} -{{ include "oracle-client-component-label" . | indent 4 }} -spec: - podManagementPolicy: Parallel - updateStrategy: - type: RollingUpdate - replicas: {{ .Values.oracle.replicas }} - serviceName: oracle - selector: - matchLabels: -{{ include "labels" . | indent 6 }} -{{ include "oracle-client-component-label" . | indent 6 }} - template: - metadata: - labels: -{{ include "labels" . | indent 8 }} -{{ include "oracle-client-component-label" . | indent 8 }} - annotations: -{{ if .Values.oracle.metrics.enabled }} -{{ include "metric-annotations" . | indent 8 }} -{{ end }} - spec: -{{ if .Values.kube.serviceAccountSecretNames }} - initContainers: - - name: set-metadata - image: {{ .Values.kubectl.image.repository }}:{{ .Values.kubectl.image.tag }} - command: - - /bin/bash - - -c - args: - - | - RID=${POD_NAME##*-} - TOKEN_ENV_VAR_NAME="TOKEN_$RID" - {{ if (eq .Values.kube.cloudProvider "azure") }} - # Azure - CMD="label pod $POD_NAME aadpodidbinding=$POD_NAME-identity-binding" - {{ else }} - # AWS - ROLE_ARNS={{- range $index, $identity := .Values.oracle.identities -}}{{ $identity.aws.roleArn }},{{- end }} - ROLE_ARN=`echo -n $ROLE_ARNS | cut -d ',' -f $((RID + 1))` - CMD="annotate pod $POD_NAME iam.amazonaws.com/role=$ROLE_ARN" - {{ end }} - - kubectl \ - --namespace "$POD_NAMESPACE" \ - --server="https://kubernetes.default.svc" \ - --token="${!TOKEN_ENV_VAR_NAME}" \ - --certificate-authority="/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" \ - --overwrite=true \ - $CMD - env: - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - {{ range $index, $e := .Values.kube.serviceAccountSecretNames }} - - name: TOKEN_{{ $index }} - valueFrom: - secretKeyRef: - key: token - name: {{ $e }} - {{ end }} -{{ end }} - containers: - - name: oracle-client - image: {{ .Values.image.repository }}:{{ .Values.image.tag }} - imagePullPolicy: Always - ports: - - name: prometheus - containerPort: {{ .Values.oracle.metrics.prometheusPort }} - command: - - bash - - "-c" - - | - [[ $REPLICA_NAME =~ -([0-9]+)$ ]] || exit 1 - RID=${BASH_REMATCH[1]} - - # Set the private key path. If Azure HSM signing is specified, - # it will take precedence. - export PRIVATE_KEY_PATH="/private-keys/private-key-$RID" - - # Get the correct key vault name. If this oracle's identity is not - # using Azure HSM signing, the key vault name will be empty and ignored - AZURE_KEY_VAULT_NAMES={{- range $index, $identity := .Values.oracle.identities -}}{{- if (hasKey $identity "azure" ) -}}{{ $identity.azure.keyVaultName | default "" }}{{- end }},{{- end }} - export AZURE_KEY_VAULT_NAME=`echo -n $AZURE_KEY_VAULT_NAMES | cut -d ',' -f $((RID + 1))` - - # Get the correct oracle account address - ADDRESSES={{- range $index, $identity := .Values.oracle.identities -}}{{ $identity.address }},{{- end }} - export ADDRESS=`echo -n $ADDRESSES | cut -d ',' -f $((RID + 1))` - - exec yarn start - env: - - name: REPLICA_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: API_KEYS - valueFrom: - secretKeyRef: - key: api_keys - name: {{ template "api-keys-secret-name" . }} -{{ include "common.env-var" (dict "name" "API_REQUEST_TIMEOUT" "dict" .Values.oracle "value_name" "apiRequestTimeoutMs" "optional" true) | indent 8 }} -{{ include "common.env-var" (dict "name" "AZURE_HSM_INIT_TRY_COUNT" "dict" .Values.oracle.azureHsm "value_name" "initTryCount") | indent 8 }} -{{ include "common.env-var" (dict "name" "AZURE_HSM_INIT_MAX_RETRY_BACKOFF_MS" "dict" .Values.oracle.azureHsm "value_name" "initMaxRetryBackoffMs") | indent 8 }} -{{ include "common.env-var" (dict "name" "CIRCUIT_BREAKER_PRICE_CHANGE_THRESHOLD" "dict" .Values.oracle "value_name" "circuitBreakerPriceChangeThreshold") | indent 8 }} -{{ include "common.env-var" (dict "name" "CURRENCY_PAIR" "dict" .Values.oracle "value_name" "currencyPair") | indent 8 }} -{{ include "common.env-var" (dict "name" "MINIMUM_PRICE_SOURCES" "dict" .Values.oracle "value_name" "minPriceSourceCount") | indent 8 }} -{{ include "common.env-var" (dict "name" "PRICE_SOURCES" "dict" .Values.oracle "value_name" "priceSources") | indent 8 }} -{{ include "common.env-var" (dict "name" "GAS_PRICE_MULTIPLIER" "dict" .Values.oracle "value_name" "gasPriceMultiplier") | indent 8 }} -{{ include "common.env-var" (dict "name" "HTTP_RPC_PROVIDER_URL" "dict" .Values.oracle.rpcProviderUrls "value_name" "http") | indent 8 }} -{{ include "common.env-var" (dict "name" "MAX_BLOCK_TIMESTAMP_AGE_MS" "dict" .Values.oracle "value_name" "maxBlockTimestampAgeMs" "optional" true) | indent 8 }} -{{ include "common.env-var" (dict "name" "METRICS" "dict" .Values.oracle.metrics "value_name" "enabled") | indent 8 }} -{{ include "common.env-var" (dict "name" "MID_AGGREGATION_MAX_PERCENTAGE_DEVIATION" "dict" .Values.oracle.aggregation.mid "value_name" "maxPercentageDeviation" "optional" true) | indent 8 }} -{{ include "common.env-var" (dict "name" "MID_AGGREGATION_MAX_EXCHANGE_VOLUME_SHARE" "dict" .Values.oracle.aggregation.mid "value_name" "maxExchangeVolumeShare" "optional" true) | indent 8 }} -{{ include "common.env-var" (dict "name" "MID_AGGREGATION_MAX_PERCENTAGE_BID_ASK_SPREAD" "dict" .Values.oracle.aggregation.mid "value_name" "maxPercentageBidAskSpread" "optional" true) | indent 8 }} -{{ include "common.env-var" (dict "name" "MIN_REPORT_PRICE_CHANGE_THRESHOLD" "dict" .Values.oracle.reporter.blockBased "value_name" "minReportPriceChangeThreshold" "optional" true) | indent 8 }} -{{ include "common.env-var" (dict "name" "OVERRIDE_INDEX" "dict" .Values.oracle "value_name" "overrideIndex" "optional" true) | indent 8 }} -{{ include "common.env-var" (dict "name" "OVERRIDE_ORACLE_COUNT" "dict" .Values.oracle "value_name" "overrideOracleCount" "optional" true) | indent 8 }} -{{ include "common.env-var" (dict "name" "PRIVATE_KEY_PATH" "dict" .Values.oracle "value_name" "privateKeyPath" "optional" true) | indent 8 }} -{{ include "common.env-var" (dict "name" "PROMETHEUS_PORT" "dict" .Values.oracle.metrics "value_name" "prometheusPort") | indent 8 }} -{{ include "common.env-var" (dict "name" "REPORT_STRATEGY" "dict" .Values.oracle "value_name" "reportStrategy") | indent 8 }} -{{ include "common.env-var" (dict "name" "REPORT_TARGET_OVERRIDE" "dict" .Values.oracle "value_name" "reportTargetOverride" "optional" true) | indent 8 }} -{{ include "common.env-var" (dict "name" "TARGET_MAX_HEARTBEAT_PERIOD_MS" "dict" .Values.oracle.reporter.blockBased "value_name" "targetMaxHeartbeatPeriodMs" "optional" true) | indent 8 }} -{{ include "common.env-var" (dict "name" "UNUSED_ORACLE_ADDRESSES" "dict" .Values.oracle "value_name" "unusedOracleAddresses") | indent 8 }} -{{ include "common.env-var" (dict "name" "WALLET_TYPE" "dict" .Values.oracle "value_name" "walletType") | indent 8 }} -{{ include "common.env-var" (dict "name" "WS_RPC_PROVIDER_URL" "dict" .Values.oracle.rpcProviderUrls "value_name" "ws") | indent 8 }} - readinessProbe: - exec: - command: - - /celo-oracle/readinessProbe.sh - - "{{ .Values.oracle.metrics.prometheusPort }}" - - "{{ .Values.oracle.currencyPair }}" - initialDelaySeconds: 10 - periodSeconds: 5 - volumeMounts: - - name: private-key-volume - readOnly: true - mountPath: "/private-keys" - volumes: - - name: private-key-volume - secret: - secretName: {{ template "pkey-secret-name" . }} diff --git a/packages/helm-charts/oracle/values.yaml b/packages/helm-charts/oracle/values.yaml deleted file mode 100644 index 3d5c9954e..000000000 --- a/packages/helm-charts/oracle/values.yaml +++ /dev/null @@ -1,62 +0,0 @@ -# This file is intended to show the expected value structure with placeholder values. -# Many values are optional, and the defaults are left up to the client. -# These values are commented out in this file, but show the correct structure -# if they were to be specified. - -environment: - name: test - -image: - repository: oracletest.azurecr.io/test/oracle - tag: hsmtest - -kubectl: - image: - repository: bitnami/kubectl - tag: 1.17.4 - -kube: - cloudProvider: azure - -oracle: - replicas: 2 - rpcProviderUrls: - ws: wss://alfajoresstaging-forno.celo-testnet.org - http: https://alfajoresstaging-forno.celo-testnet.org - identities: - - address: "0x0000000000000000000000000000000000000000" - azure: - id: defaultId - clientId: defaultClientId - keyVaultName: defaultKeyVaultName - - address: "0x0000000000000000000000000000000000000001" - azure: - id: defaultId1 - clientId: defaultClientId1 - keyVaultName: defaultKeyVaultName1 - azureHsm: - initTryCount: 5 - initMaxRetryBackoffMs: 30000 - aggregation: - mid: - maxExchangeVolumeShare: 1 - askMaxPercentageDeviation: 0.05 - bidMaxPercentageDeviation: 0.05 - maxPercentageBidAskSpread: 0.025 - # minReportPriceChangeThreshold - metrics: - enabled: true - prometheusPort: 9090 - apiRequestTimeoutMs: 5000 - circuitBreakerPriceChangeThreshold: 0.25 - gasPriceMultiplier: 6 - reportStrategy: BLOCK_BASED - reporter: - blockBased: - minReportPriceChangeThreshold: 0.005 # 0.5% - # targetMaxHeartbeatPeriodMs - # privateKeyPath - # unusedOracleAddresses - # overrideIndex - # overrideOracleCount - # maxBlockTimestampAgeMs diff --git a/packages/helm-charts/prometheus-stackdriver/Chart.yaml b/packages/helm-charts/prometheus-stackdriver/Chart.yaml deleted file mode 100644 index 9ce46dd13..000000000 --- a/packages/helm-charts/prometheus-stackdriver/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for installing prometheus and the stackdriver-prometheus-sidecar -name: prometheus-stackdriver -version: 0.1.0 diff --git a/packages/helm-charts/prometheus-stackdriver/templates/_helpers.tpl b/packages/helm-charts/prometheus-stackdriver/templates/_helpers.tpl deleted file mode 100644 index d7be3393d..000000000 --- a/packages/helm-charts/prometheus-stackdriver/templates/_helpers.tpl +++ /dev/null @@ -1,58 +0,0 @@ -{{/* -Expand the name of the chart. -*/}} -{{- define "prometheus-stackdriver.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "prometheus-stackdriver.fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "prometheus-stackdriver.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "prometheus-stackdriver.labels" -}} -helm.sh/chart: {{ include "prometheus-stackdriver.chart" . }} -{{ include "prometheus-stackdriver.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "prometheus-stackdriver.selectorLabels" -}} -app.kubernetes.io/name: {{ include "prometheus-stackdriver.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define "prometheus-stackdriver.serviceAccountName" -}} -{{- default (include "prometheus-stackdriver.fullname" .) .Values.serviceAccount.name }} -{{- end }} diff --git a/packages/helm-charts/prometheus-stackdriver/templates/configmap.yaml b/packages/helm-charts/prometheus-stackdriver/templates/configmap.yaml deleted file mode 100644 index 613631d32..000000000 --- a/packages/helm-charts/prometheus-stackdriver/templates/configmap.yaml +++ /dev/null @@ -1,177 +0,0 @@ -#Copyright 2019 Google LLC - -#Licensed under the Apache License, Version 2.0 (the "License"); -#you may not use this file except in compliance with the License. -#You may obtain a copy of the License at - -#https://www.apache.org/licenses/LICENSE-2.0 - -#Unless required by applicable law or agreed to in writing, software -#distributed under the License is distributed on an "AS IS" BASIS, -#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -#See the License for the specific language governing permissions and -#limitations under the License. - -apiVersion: v1 -kind: ConfigMap -metadata: - name: prometheus-server-conf - labels: -{{ include "prometheus-stackdriver.labels" . | indent 4 }} -data: - prometheus.yml: |- - global: - scrape_interval: 60s - evaluation_interval: 5s - # Label the metrics with a custom label if using multiple prometheus for same environments - external_labels: - cluster_name: {{ required "Valid .Values.cluster entry required!" .Values.cluster }} - - {{- if .Values.remote_write }} - remote_write: - - basic_auth: - password: {{ .Values.remote_write.basic_auth.password }} - username: {{ .Values.remote_write.basic_auth.username }} - url: {{ .Values.remote_write.url }} - write_relabel_configs: - {{- with .Values.remote_write.write_relabel_configs }} - {{- toYaml . | nindent 8 }} - {{- end }} - {{- end }} - - scrape_configs: - {{- if .Values.jobs.prometheus | default true }} - - job_name: 'prometheus' - scrape_interval: 20s - static_configs: - - targets: ['localhost:9090'] - {{- end }} - - {{- if .Values.jobs.kubernetes_apiservers | default true }} - - job_name: 'kubernetes-apiservers' - kubernetes_sd_configs: - - role: endpoints - scheme: https - tls_config: - ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt - bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token - relabel_configs: - - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] - action: keep - regex: default;kubernetes;https - {{- end }} - - {{- if .Values.jobs.kubernetes_nodes | default true }} - - job_name: 'kubernetes-nodes' - scheme: https - tls_config: - ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt - bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token - kubernetes_sd_configs: - - role: node - relabel_configs: - - action: labelmap - regex: __meta_kubernetes_node_label_(.+) - - target_label: __address__ - replacement: kubernetes.default.svc:443 - - source_labels: [__meta_kubernetes_node_name] - regex: (.+) - target_label: __metrics_path__ - replacement: /api/v1/nodes/${1}/proxy/metrics - {{- end }} - - {{- if .Values.jobs.kubernetes_pods | default true }} - - job_name: 'kubernetes-pods' - kubernetes_sd_configs: - - role: pod - relabel_configs: - - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] - action: keep - regex: true - - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path] - action: replace - target_label: __metrics_path__ - regex: (.+) - - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port] - action: replace - regex: ([^:]+)(?::\d+)?;(\d+) - replacement: $1:$2 - target_label: __address__ - - action: labelmap - regex: __meta_kubernetes_pod_label_(.+) - - source_labels: [__meta_kubernetes_namespace] - action: replace - target_label: kubernetes_namespace - - source_labels: [__meta_kubernetes_pod_name] - action: replace - target_label: kubernetes_pod_name - {{- end }} - - {{- if .Values.jobs.kubernetes_cadvisor | default true }} - - job_name: 'kubernetes-cadvisor' - scheme: https - tls_config: - ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt - bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token - kubernetes_sd_configs: - - role: node - relabel_configs: - - action: labelmap - regex: __meta_kubernetes_node_label_(.+) - - target_label: __address__ - replacement: kubernetes.default.svc:443 - - source_labels: [__meta_kubernetes_node_name] - regex: (.+) - target_label: __metrics_path__ - replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor - {{- end }} - - {{- if .Values.jobs.kubernetes_service_endpoints | default true }} - - job_name: 'kubernetes-service-endpoints' - kubernetes_sd_configs: - - role: endpoints - relabel_configs: - - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape] - action: keep - regex: true - - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme] - action: replace - target_label: __scheme__ - regex: (https?) - - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path] - action: replace - target_label: __metrics_path__ - regex: (.+) - - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port] - action: replace - target_label: __address__ - regex: ([^:]+)(?::\d+)?;(\d+) - replacement: $1:$2 - - action: labelmap - regex: __meta_kubernetes_service_label_(.+) - - source_labels: [__meta_kubernetes_namespace] - action: replace - target_label: kubernetes_namespace - - source_labels: [__meta_kubernetes_service_name] - action: replace - target_label: kubernetes_name - {{- end }} - -{{- if .Values.scrapeJob }} - {{- if .Values.scrapeJob.Name }} - - job_name: {{ .Values.scrapeJob.Name }} - {{- end }} - static_configs: - {{- if .Values.scrapeJob.Targets }} - - targets: - {{- range .Values.scrapeJob.Targets }} - - {{ . }} - {{- end -}} - {{- end -}} - {{ if .Values.scrapeJob.Labels }} - labels: - {{- range .Values.scrapeJob.Labels }} - {{ . }} - {{- end -}} - {{- end -}} -{{- end -}} \ No newline at end of file diff --git a/packages/helm-charts/prometheus-stackdriver/templates/deployment.yaml b/packages/helm-charts/prometheus-stackdriver/templates/deployment.yaml deleted file mode 100644 index a053d85ee..000000000 --- a/packages/helm-charts/prometheus-stackdriver/templates/deployment.yaml +++ /dev/null @@ -1,103 +0,0 @@ -#Copyright 2019 Google LLC - -#Licensed under the Apache License, Version 2.0 (the "License"); -#you may not use this file except in compliance with the License. -#You may obtain a copy of the License at - -#https://www.apache.org/licenses/LICENSE-2.0 - -#Unless required by applicable law or agreed to in writing, software -#distributed under the License is distributed on an "AS IS" BASIS, -#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -#See the License for the specific language governing permissions and -#limitations under the License. - -apiVersion: apps/v1 -kind: Deployment -metadata: - name: prometheus - labels: -{{ include "prometheus-stackdriver.labels" . | indent 4 }} -spec: - replicas: 1 - strategy: - type: Recreate - selector: - matchLabels: - app: prometheus-server - template: - metadata: - annotations: - prometheus.io/scrape: "true" - prometheus.io/path: "/metrics" - prometheus.io/port: "9090" - labels: -{{ include "prometheus-stackdriver.labels" . | indent 8 }} - app: prometheus-server - spec: - securityContext: - runAsUser: 1000 - runAsGroup: 1000 - fsGroup: 1000 - serviceAccountName: {{ .Values.serviceAccount.name }} - containers: - - name: prometheus - image: prom/prometheus:{{ .Values.prometheus.imageTag }} - resources: - requests: - memory: 4Gi - cpu: 2 - args: - - "--config.file=/etc/prometheus/prometheus.yml" - - "--storage.tsdb.retention.time={{ .Values.prometheus.retention_time | default "7d" }}" - - "--storage.tsdb.path=/prometheus/" - ports: - - containerPort: 9090 - volumeMounts: - - name: prometheus-config-volume - mountPath: /etc/prometheus/ - - name: prometheus-storage-volume - mountPath: /prometheus/ -{{- if not .Values.stackdriver.disabled }} - - name: sidecar - image: gcr.io/stackdriver-prometheus/stackdriver-prometheus-sidecar:{{ .Values.stackdriver.sidecar.imageTag }} - imagePullPolicy: Always - args: - - --stackdriver.project-id={{ .Values.gcloud.project }} - - --prometheus.wal-directory=/prometheus/wal - - --stackdriver.kubernetes.location={{ .Values.gcloud.region }} - - --stackdriver.kubernetes.cluster-name={{ .Values.cluster }} -{{ if .Values.stackdriver.includeFilter -}} -{{ indent 12 (printf "- --include=%s" .Values.stackdriver.includeFilter) }} -{{- end -}} -{{/* This used to be enabled, but now is not. Enable this for oracle clusters only. */}} -{{- if (and true .Values.stackdriver.metricsPrefix) }} - - --stackdriver.metrics-prefix={{ .Values.stackdriver.metricsPrefix }} -{{- end }} - ports: - - name: sidecar - containerPort: 9091 - volumeMounts: - - name: prometheus-storage-volume - mountPath: /prometheus -{{- if not (kindIs "invalid" .Values.stackdriver.gcloudServiceAccountKeyBase64) }} - - name: prometheus-service-account-key - mountPath: /var/secrets/google - env: - - name: GOOGLE_APPLICATION_CREDENTIALS - value: /var/secrets/google/prometheus-service-account.json -{{- end }} -{{- end }} - volumes: - - name: prometheus-config-volume - configMap: - defaultMode: 420 - name: prometheus-server-conf - - name: prometheus-storage-volume - persistentVolumeClaim: - claimName: prometheus -{{- if not (kindIs "invalid" .Values.stackdriver.gcloudServiceAccountKeyBase64) }} - - name: prometheus-service-account-key - secret: - secretName: prometheus-service-account-key -{{- end }} diff --git a/packages/helm-charts/prometheus-stackdriver/templates/gcloud-service-account-key-secret.yaml b/packages/helm-charts/prometheus-stackdriver/templates/gcloud-service-account-key-secret.yaml deleted file mode 100644 index 34527b976..000000000 --- a/packages/helm-charts/prometheus-stackdriver/templates/gcloud-service-account-key-secret.yaml +++ /dev/null @@ -1,11 +0,0 @@ -{{- if not (kindIs "invalid" .Values.stackdriver.gcloudServiceAccountKeyBase64) }} -apiVersion: v1 -kind: Secret -metadata: - name: prometheus-service-account-key - labels: -{{ include "prometheus-stackdriver.labels" . | indent 4 }} -type: Opaque -data: - prometheus-service-account.json: {{ .Values.stackdriver.gcloudServiceAccountKeyBase64 }} -{{ end -}} diff --git a/packages/helm-charts/prometheus-stackdriver/templates/prometheus-pvc.yaml b/packages/helm-charts/prometheus-stackdriver/templates/prometheus-pvc.yaml deleted file mode 100644 index 2cafdaa9a..000000000 --- a/packages/helm-charts/prometheus-stackdriver/templates/prometheus-pvc.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - labels: -{{ include "prometheus-stackdriver.labels" . | indent 4 }} - name: prometheus -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: {{ .Values.storageSize }} -{{- if .Values.storageClassName }} - storageClassName: {{ .Values.storageClassName }} -{{- end }} diff --git a/packages/helm-charts/prometheus-stackdriver/templates/service-account.yaml b/packages/helm-charts/prometheus-stackdriver/templates/service-account.yaml deleted file mode 100644 index 3dd19cb03..000000000 --- a/packages/helm-charts/prometheus-stackdriver/templates/service-account.yaml +++ /dev/null @@ -1,62 +0,0 @@ -#Copyright 2019 Google LLC - -#Licensed under the Apache License, Version 2.0 (the "License"); -#you may not use this file except in compliance with the License. -#You may obtain a copy of the License at - -#https://www.apache.org/licenses/LICENSE-2.0 - -#Unless required by applicable law or agreed to in writing, software -#distributed under the License is distributed on an "AS IS" BASIS, -#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -#See the License for the specific language governing permissions and -#limitations under the License. - -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: prometheus - labels: - {{- include "prometheus-stackdriver.labels" . | nindent 4 }} -rules: -- apiGroups: [""] - resources: - - nodes - - nodes/proxy - - services - - endpoints - - pods - verbs: ["get", "list", "watch"] -- apiGroups: - - extensions - resources: - - ingresses - verbs: ["get", "list", "watch"] -- nonResourceURLs: ["/metrics"] - verbs: ["get"] ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: prometheus - labels: -{{ include "prometheus-stackdriver.labels" . | indent 4 }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: prometheus -subjects: -- kind: ServiceAccount - name: {{ include "prometheus-stackdriver.serviceAccountName" . }} - namespace: {{ .Release.Namespace }} ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "prometheus-stackdriver.serviceAccountName" . }} - labels: - {{- include "prometheus-stackdriver.labels" . | nindent 4 }} - {{- with .Values.serviceAccount.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} diff --git a/packages/helm-charts/prometheus-stackdriver/templates/service.yaml b/packages/helm-charts/prometheus-stackdriver/templates/service.yaml deleted file mode 100644 index c374552cf..000000000 --- a/packages/helm-charts/prometheus-stackdriver/templates/service.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: prometheus-server - labels: -{{ include "prometheus-stackdriver.labels" . | indent 4 }} -spec: - ports: - - name: web - port: 9090 - protocol: TCP - targetPort: 9090 - selector: - app: prometheus-server - sessionAffinity: None - type: ClusterIP - diff --git a/packages/helm-charts/prometheus-stackdriver/values.yaml b/packages/helm-charts/prometheus-stackdriver/values.yaml deleted file mode 100644 index 201a465f9..000000000 --- a/packages/helm-charts/prometheus-stackdriver/values.yaml +++ /dev/null @@ -1,230 +0,0 @@ -cluster: null - -gcloud: - project: null - region: null - -namespace: prometheus - -jobs: {} - -prometheus: - imageTag: v2.27.1 - retention_time: 7d - -# TODO: remove values from the .env files... -scrapeJob: {} - # Labels: null - # Name: null - # Targets: null - -serviceAccount: - # Annotations to add to the service account - annotations: {} - # The name of the service account to use. - # If not set and create is true, a name is generated using the fullname template - name: null - -stackdriver: - disabled: true - # When sending metrics from outside GCP to GCP Stackdriver. - gcloudServiceAccountKeyBase64: null - # To save $, don't send metrics to SD that probably won't be used. - # nginx metrics currently breaks sidecar. - # Stackdriver allows a maximum of 10 custom labels. - # kube-state-metrics has some metrics of the form "kube_.+_labels" - # that provides the labels of k8s resources as metric labels. - # If some k8s resources have too many labels, this results in a bunch of - # errors when the sidecar tries to send metrics to Stackdriver. - includeFilter: >- - {job=~".+", - __name__!~"apiserver_.+", - __name__!~"container_cpu_load_average_10s", - __name__!~"container_cpu_system_seconds_total", - __name__!~"container_cpu_user_seconds_total", - __name__!~"container_file_.+", - __name__!~"container_fs_[^w].+", - __name__!~"container_last_.+", - __name__!~"container_memory_[^uw].*", - __name__!~"container_network_.+", - __name__!~"container_processes", - __name__!~"container_sockets", - __name__!~"container_spec_.+", - __name__!~"container_start_.+", - __name__!~"container_tasks_state", - __name__!~"container_threads", - __name__!~"container_threads_max", - __name__!~"erlang_.+", - __name__!~"etcd_.+", - __name__!~"kube_.+_labels", - __name__!~"kube_certificatesigningrequest_.+", - __name__!~"kube_configmap_.+", - __name__!~"kube_cronjob_.+", - __name__!~"kube_endpoint_.+", - __name__!~"kube_horizontalpodautoscaler_.+", - __name__!~"kube_ingress_.+", - __name__!~"kube_job_.+", - __name__!~"kube_lease_.+", - __name__!~"kube_limitrange_.+", - __name__!~"kube_mutatingwebhookconfiguration_.+", - __name__!~"kube_namespace_.+", - __name__!~"kube_networkpolicy_.+", - __name__!~"kube_pod_[^cs].+", - __name__!~"kube_pod_container_[^r].+", - __name__!~"kube_pod_container_status_last_terminated_reason", - __name__!~"kube_pod_container_status_terminated_reason", - __name__!~"kube_pod_container_status_waiting_reason", - __name__!~"kube_poddisruptionbudget_.+", - __name__!~"kube_replicaset_.+", - __name__!~"kube_replicationcontroller_.+", - __name__!~"kube_resourcequota_.+", - __name__!~"kube_secret_.+", - __name__!~"kube_service_.+", - __name__!~"kube_node_status_condition", - __name__!~"kube_storageclass_.+", - __name__!~"kube_service_.+", - __name__!~"kube_validatingwebhookconfiguration_.+", - __name__!~"kube_verticalpodautoscaler_.+", - __name__!~"kube_volumeattachment_.+", - __name__!~"kubelet_.+", - __name__!~"nginx_.+", - __name__!~"phoenix_.+", - __name__!~"rest_client_.+", - __name__!~"storage_.+", - __name__!~"workqueue_.+"} - # metricsPrefix: external.googleapis.com/prometheus/prefix - sidecar: - imageTag: 0.7.3 - -# storageClassName: null -storageSize: 50Gi - -remote_write: - url: null - basic_auth: - username: null - password: null - write_relabel_configs: - - action: drop - regex: "(aadpodidentity.*\ - |aggregator_.*\ - |apiserver_.+\ - |authentication.*\ - |cadvisor_version_info\ - |certmanager.*\ - |cloudprovider_gce.*\ - |configconnector.*\ - |container_blkio.*\ - |container_cpu_cfs_throttled_seconds_total\ - |container_cpu_load_average_10s\ - |container_cpu_system_seconds_total\ - |container_cpu_user_seconds_total\ - |container_file_.+\ - |container_fs_.+\ - |container_last_.+\ - |container_memory_[^wu].*\ - |container_network_.+\ - |container_processes\ - |container_scrape_error\ - |container_sockets\ - |container_spec_.+\ - |container_start_.+\ - |container_tasks_state\ - |container_threads_max\ - |container_threads\ - |container_ulimits.*\ - |coredns.*\ - |cortex.*\ - |csi_operations.*\ - |erlang_.+\ - |etcd_.+\ - |go_gc_.*\ - |go_info.*\ - |go_memstats_.*\ - |go_threads.*\ - |grpc_client_.*\ - |jaeger_.*\ - |kube_configmap.*\ - |kube_deployment_created\ - |kube_deployment_labels\ - |kube_deployment_metadata_generation\ - |kube_deployment_spec_paused\ - |kube_deployment_spec_replicas\ - |kube_deployment_spec_strategy_rollingupdate_max_surge\ - |kube_deployment_spec_strategy_rollingupdate_max_unavailable\ - |kube_deployment_status_condition\ - |kube_deployment_status_observed_generation\ - |kube_deployment_status_replicas_unavailable\ - |kube_deployment_status_replicas_updated\ - |kube_endpoint.*\ - |kube_job.*\ - |kube_namespace.*\ - |kube_node_status_condition\ - |kube_persistentvolume.*\ - |kube_pod_[^cs].+\ - |kube_pod_container_info\ - |kube_pod_container_state_started\ - |kube_pod_container_status_last_terminated_reason\ - |kube_pod_container_status_ready\ - |kube_pod_container_status_running\ - |kube_pod_container_status_terminated_reason\ - |kube_pod_container_status_terminated\ - |kube_pod_container_status_waiting_reason\ - |kube_pod_container_status_waiting\ - |kube_pod_status_ready\ - |kube_pod_status_scheduled\ - |kube_pod_status_scheduled_time\ - |kube_replicaset.*\ - |kube_resourcequota.*\ - |kube_secret_.+\ - |kube_service.*\ - |kubedns.*\ - |kubelet_[^v].+\ - |loki.*\ - |machine_cpu_physical_cores\ - |machine_cpu_sockets\ - |machine_scrape.*\ - |net_conntrack_.*\ - |nginx_.+\ - |nodejs_active_.*\ - |nodejs_gc_.*\ - |oracle_action_duration_bucket\ - |oracle_exchange_api_request_duration_seconds_bucket\ - |oracle_exchange_api_request_error_count\ - |oracle_ticker_property\ - |phoenix_.+\ - |process_cpu_system.*\ - |process_cpu_user.*\ - |process_disk_reads_total\ - |process_disk_writes_total\ - |process_heap_bytes\ - |process_involuntary_context_switches_total\ - |process_io_pagefaults_total\ - |process_max_fds\ - |process_max_resident_memory_bytes\ - |process_noio_pagefaults_total\ - |process_open_fds\ - |process_signals_delivered_total\ - |process_start_time_seconds\ - |process_swaps_total\ - |process_threads_total\ - |process_uptime_seconds\ - |process_virtual_memory_bytes\ - |process_virtual_memory_max_bytes\ - |process_voluntary_context_switches_total\ - |prometheus.*\ - |promhttp_.*\ - |python.*\ - |relay_nodejs_gc_.*\ - |rest_client_.+\ - |scrape.*\ - |state_.+\ - |storage_.+\ - |workqueue_.+)" - source_labels: [__name__] - - action: drop - regex: lens-metrics - source_labels: [kubernetes_namespace] - - action: drop - regex: (container_.*|kube_.*);(kube.+|lens-metrics|default|kong|pl) - source_labels: [__name__,namespace] diff --git a/packages/helm-charts/promtail/README.md b/packages/helm-charts/promtail/README.md deleted file mode 100644 index 727d8d242..000000000 --- a/packages/helm-charts/promtail/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# Promtail - -Helm chart values to manage the Promtail deployment used to ingest k8s logs into Grafana Cloud's Loki instance. - -- Documentation: - - - - -- Helm repo: -- Code: - -## Configuration - -- Promtail ingests Kubernetes logs from allow-listed namespaces. -- Nothing else gets scraped (eg: ) — to be re-evaluated. -- Promtail exposes metrics to Prometheus, which can scrape them. See . -- Each k8s cluster has its own ServiceAccount. - -## Querying logs - -Head to and select the logs datasource. -Have a look at the LogQL specs: . - -## Deployment - -Use `celotool`: - -```sh -celotool deploy {initial,upgrade,destroy} promtail -e [--context ] -``` diff --git a/packages/helm-charts/promtail/values.yaml b/packages/helm-charts/promtail/values.yaml deleted file mode 100644 index f48a513aa..000000000 --- a/packages/helm-charts/promtail/values.yaml +++ /dev/null @@ -1,41 +0,0 @@ -annotations: - # Enable Prometheus scraping of log based metrics, - # see https://grafana.com/docs/loki/latest/clients/promtail/configuration/#pipeline_stages: metrics - prometheus.io/scrape: 'true' - prometheus.io/port: 'http-metrics' - -config: - # add a destination for the logs ingestion - # lokiAddress: - - snippets: - pipelineStages: - - cri: {} - - docker: {} - - extraRelabelConfigs: - # Do not ingest logs for fluentd. - - action: drop - source_labels: - - app - regex: fluentd-log-agent - # Keep Kubernetes pod labels. - - action: labelmap - regex: __meta_kubernetes_pod_label_(.+) - # Only keep logs from these namespaces. - - action: keep - source_labels: - - namespace - # TODO: reconsider what should be kept from the default namespace - # eg: ingress controller - regex: (alfajores|baklava|blockscout|default|komenci|rc1|rc1staging|staging|walletconnect) - - action: labeldrop - regex: (app_kubernetes_io_component|app_kubernetes_io_instance|app.kubernetes.io/managed-by|app_kubernetes_io_managed_by|app_kubernetes_io_name|app_kubernetes_io_version|controller-revision-hash|controller_revision_hash|pod_template_hash|filename) - -serviceAccount: - # add a iam.gke.io/gcp-service-account, see - # https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity#gcloud - annotations: {} - -updateStrategy: - type: RollingUpdate diff --git a/packages/helm-charts/testnet/Chart.yaml b/packages/helm-charts/testnet/Chart.yaml deleted file mode 100644 index 530e15678..000000000 --- a/packages/helm-charts/testnet/Chart.yaml +++ /dev/null @@ -1,22 +0,0 @@ ---- -name: testnet -apiVersion: v1 -version: 0.2.1 -description: private Ethereum network Helm chart for Kubernetes -keywords: - - celo - - ethereum - - blockchain -home: https://www.celo.org/ -sources: - - https://github.com/celo-org/celo-monorepo -maintainers: - - name: celo - email: contact@celo.org -icon: https://avatars1.githubusercontent.com/u/37552875?s=200&v=4 -appVersion: v1.0.0 -dependencies: - - name: common - repository: oci://us-west1-docker.pkg.dev/devopsre/clabs-public-oci - version: 0.2.7 - diff --git a/packages/helm-charts/testnet/README.md b/packages/helm-charts/testnet/README.md deleted file mode 100644 index 45c1f0f69..000000000 --- a/packages/helm-charts/testnet/README.md +++ /dev/null @@ -1,132 +0,0 @@ -# Testnet Helm Chart - -This helm chart allows you to deploy testnets, on which you can deploy smart contracts or interact with our app. See the README at the parent folder for more general Helm - -`NAMESPACE_NAME` is the Kubernetes namespace all Kubernetes primitives are getting deployed to. This isolates various networks from each other. `RELEASE_NAME` is the helm chart release name, i.e. a consistent name that refers to the primitives as a group. By convention, `NAMESPACE_NAME` and `RELEASE_NAME` should be the same name and just use [a-z0-9\-] characters so that most scripts you just pass `NAME` instead of having to specify all the names separately. However if you would like to, you can generally use the `-r` or `-n` flags to do so. - -(These commands assume your current path is at packages/helm-charts ) - -Deploy a release of the helm chart by running the following command: - -```bash -export NAME=my-name -./testnet/scripts/create-network.sh -r $NAME -``` - -> if you are deploying to non-development envs(i.e. testnet_dev, testnet_staging or testnet_prod), pass also `celo-testnet` as domain name -> or the ethstats domain will not resolve properly: `./testnet/scripts/create-network.sh -r $NAME -d celo-testnet` - -You can also upgrade an environment by passing the `-u` flag: - -```bash -export NAME=my-name -./testnet/scripts/create-network.sh -u -r $NAME -``` - -The output of the above should have more interesting instructions regarding getting info of the nodes you'll likely want to connect to. You'll have to wait a minute or two for the loadbalancers to provision. You can also use a script to produce the necessary connection info for the mobile package. - -```bash -./testnet/scripts/write-mobile-network-config.sh $NAME -``` - -If you need to connect via RPC, you can run: - -```bash -./testnet/scripts/port-forward.sh $NAME -``` - -All the port-forward script really does is find the pod under the `gethminer1` service of your release and port-forwards it to your machine. - -So a contract deploy as per [protocol README](../../protocol/README.md) would look like: - -```bash -# pwd: .../packages/protocol -# portforward is active -# Don't forget to set $NAME in the new terminal -yarn run init-network -n $NAME -``` - -You can then share the contract build artifacts by running: - -```bash -yarn run upload-artifacts -n $NAME -``` - -This will upload the build artifacts to the cluster, and can be consequently downloaded via: - -```bash -yarn run download-artifacts -n $NAME -``` - -This will download the build artifacts to your build folder, as if you deployed the contracts yourself. - -You should be sure to update the appropriate yaml file in `packages/blockchain-api/` with the addresses of the GoldToken and StableToken proxy contracts. - -The last step is to update the contract ABIs and addresses for use in the mobile app as per [mobile README](../../mobile/README.md) - -```bash -# pwd: .../packages/mobile -yarn run update-contracts --testnets=testnet_prod,integration,argentinastaging,argentinaproduction,$NAME -``` - -After you are done, you can (and should after usage) teardown your testnet by running: - -```console -./testnet/scripts/destroy-network.sh -r $NAME -``` - -## Geth Docker Images - -Docker images for Geth (and other services) are built automatically by [Google Cloud Build](https://console.cloud.google.com/cloud-build/triggers?organizationId=54829595577&project=celo-testnet) when a PR is raised or merged to master. - -To try out local changes to Geth, use `celotool`. Alternatively, to deploy a dev version of Geth to a Helm release without pushing commits, you can build your own Docker image locally. - -First, install [Docker](https://store.docker.com/editions/community/docker-ce-desktop-mac). You'll need to create an account with Docker to do this. It's a bit painful to install Docker via Homebrew. - -Then run: - -```console -cd $CELO/geth -make clean && make all -./dockerize_testnet.sh -p PROJECT_ID -t TAG -``` - -where TAG is any old string. - -For a Docker build reflecting an actual commit of geth we tend to use the commit hash: - -```console -git rev-parse HEAD -``` - -This script will produce and upload two Docker images (one for Geth regular nodes, and one for the Bootnode) to the [GCP Container Registry](https://console.cloud.google.com/gcr/images/celo-testnet/GLOBAL/testnet-geth) under `gcr.io/PROJECT_ID/testnet-geth:TAG`. - -You can then start a network with your custom builds by modifying the `geth/image/repository/tag` value in `values.yaml`. (Alternatively you can pass the values in your `helm install` command with `--set geth.miner.tag=TAG` but that makes it harder to use `create-network` and other scripts). - -When you are finally happy with your changes to geth: - -- Raise a PR and get that reviewed and merged -- Identify the tag for the latest Docker image built -- Update the value in the geth.miner.tag field in `values.yaml` and raise a PR - -## Configuration - -The following table lists the configurable parameters of the vault chart and their default values. - -| Parameter | Description | Default | -| --------------------------- | ------------------------------------------------------------------ | ---------------------------- | -| `imagePullPolicy` | Container pull policy | `IfNotPresent` | -| `nodeSelector` | Node labels for pod assignmen | | -| `bootnode.image.repository` | bootnode container image to use | `ethereum/client-go` | -| `bootnode.image.tag` | bootnode container image tag to deploy | `alltools-v1.7.3` | -| `geth.image.repository` | geth container image to use | `ethereum/client-go` | -| `geth.image.tag` | geth container image tag to deploy | `v1.7.3` | -| `geth.tx.replicaCount` | geth transaction nodes replica count | `1` | -| `geth.miner.replicaCount` | geth miner nodes replica count | `1` | -| `geth.miner.account.secret` | geth account secret | `my-secret-account-password` | -| `geth.genesis.networkId` | Ethereum network id | `1101` | -| `geth.genesis.difficulty` | Ethereum network difficulty | `0x0400` | -| `geth.genesis.gasLimit` | Ethereum network gas limit | `0x8000000` | -| `geth.account.address` | Geth Account to be initially funded and deposited with mined Ether | | -| `geth.account.privateKey` | Geth Private Key | | -| `geth.account.secret` | Geth Account Secret | | diff --git a/packages/helm-charts/testnet/scripts/create-network.sh b/packages/helm-charts/testnet/scripts/create-network.sh deleted file mode 100755 index 2e89fbe17..000000000 --- a/packages/helm-charts/testnet/scripts/create-network.sh +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -NAMESPACE="" -RELEASE="" -DOMAIN_NAME_OPT="" -ACTION=install -TEST_OPT="" -ZONE="us-west1-a" - -while getopts ':utn:r:z:d:v:a:' flag; do - case "${flag}" in - u) ACTION=upgrade ;; - t) TEST_OPT="--debug --dry-run" ;; - n) NAMESPACE="${OPTARG}" ;; - r) RELEASE="${OPTARG}" ;; - z) ZONE="${OPTARG}" ;; - d) DOMAIN_NAME_OPT="--set domain.name=${OPTARG}" ;; - a) VERIFICATION_REWARDS_ADDRESS="${OPTARG}" ;; - *) echo "Unexpected option ${flag}" ;; - esac -done -shift $((OPTIND -1)) - -[ -z "$RELEASE" ] && echo "Need to set release via the -r flag" && exit 1; -[ -z "$NAMESPACE" ] && NAMESPACE=$RELEASE - -# Create blockscout DB only if we are installing -if [ "$ACTION" = "install" ]; then - - # Create a new username and password - BLOCKSCOUT_DB_USERNAME=$(openssl rand -hex 12) - BLOCKSCOUT_DB_PASSWORD=$(openssl rand -hex 24) - - if [ "z$TEST_OPT" = "z" ]; then - echo "Creating Cloud SQL database, this might take a minute or two ..." - gcloud sql instances create $RELEASE --zone $ZONE --database-version POSTGRES_9_6 --cpu 1 --memory 4G - gcloud sql users create $BLOCKSCOUT_DB_USERNAME -i $RELEASE --password $BLOCKSCOUT_DB_PASSWORD - gcloud sql databases create blockscout -i $RELEASE - kubectl create namespace $NAMESPACE - - # This command assumes the secret being available on the cluster in the default namespace - kubectl get secret blockscout-cloudsql-credentials --namespace default --export -o yaml |\ - grep -v creationTimestamp | grep -v resourceVersion | grep -v selfLink | grep -v uid | grep -v namespace |\ - kubectl apply --namespace=$NAMESPACE -f - - fi -fi - -# Get the connection name for the database -BLOCKSCOUT_DB_CONNECTION_NAME=$(gcloud sql instances describe $RELEASE --format="value(connectionName)") - -if [ "$ACTION" = "install" ]; then - - echo "Deploying new environment..." - - helm install ./testnet --name $RELEASE --namespace $NAMESPACE \ - $DOMAIN_NAME_OPT $TEST_OPT \ - --set miner.verificationrewards=$VERIFICATION_REWARDS_ADDRESS \ - --set blockscout.db.username=$BLOCKSCOUT_DB_USERNAME \ - --set blockscout.db.password=$BLOCKSCOUT_DB_PASSWORD \ - --set blockscout.db.connection_name=$BLOCKSCOUT_DB_CONNECTION_NAME - -elif [ "$ACTION" = "upgrade" ]; then - - # Get existing username and password from the database - BLOCKSCOUT_DB_USERNAME=`kubectl get secret $RELEASE-blockscout --export -o jsonpath='{.data.DB_USERNAME}' -n $NAMESPACE | base64 --decode` - BLOCKSCOUT_DB_PASSWORD=`kubectl get secret $RELEASE-blockscout --export -o jsonpath='{.data.DB_PASSWORD}' -n $NAMESPACE | base64 --decode` - - echo "Upgrading existing environment..." - - helm upgrade $RELEASE ./testnet \ - $DOMAIN_NAME_OPT $TEST_OPT \ - --set miner.verificationrewards=$VERIFICATION_REWARDS_ADDRESS \ - --set blockscout.db.username=$BLOCKSCOUT_DB_USERNAME \ - --set blockscout.db.password=$BLOCKSCOUT_DB_PASSWORD \ - --set blockscout.db.connection_name=$BLOCKSCOUT_DB_CONNECTION_NAME -fi diff --git a/packages/helm-charts/testnet/scripts/destroy-network.sh b/packages/helm-charts/testnet/scripts/destroy-network.sh deleted file mode 100755 index 4a72aeb94..000000000 --- a/packages/helm-charts/testnet/scripts/destroy-network.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -RELEASE="" -DELETE=false -[ -n "$1" ] && RELEASE=$1 -while getopts ':r:d' flag; do - case "${flag}" in - r) RELEASE="${OPTARG}" ;; - d) DELETE=true ;; - *) echo "Unexpected option ${flag}" ;; - esac -done -[ -z "$RELEASE" ] && echo "Need to set RELEASE_NAME via the -r flag" && exit 1; - -if [[ ( "$RELEASE" = "integration") || ( "$RELEASE" = "staging" ) || ( "$RELEASE" = "production" ) ]]; then - echo "You just tried to delete $RELEASE. You probably did not want to do that. Exiting the script. If this is a mistake, modify this script or do it manually" - exit 1; -fi - - -echo "You are about to delete the network $RELEASE" -if $DELETE -then - PVCS="$(kubectl get pvc --namespace=$RELEASE | grep $RELEASE | awk '{print $1}')" -fi - -gcloud sql instances delete $RELEASE -helm del --purge $RELEASE -kubectl delete namespace $RELEASE - -echo $PVCS -if $DELETE -then - while read -r pvc; do - kubectl delete pvc --namespace=$RELEASE "$pvc" - done <<< "$PVCS" - gcloud sql databases delete blockscout -i $RELEASE -fi diff --git a/packages/helm-charts/testnet/scripts/get-bootnode.sh b/packages/helm-charts/testnet/scripts/get-bootnode.sh deleted file mode 100644 index 7fb2e125e..000000000 --- a/packages/helm-charts/testnet/scripts/get-bootnode.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -apk add --no-cache curl; -CNT=0; -echo "retreiving bootnodes from $BOOTNODE_SVC" -while [ $CNT -le 90 ] -do - curl -m 5 -s $BOOTNODE_SVC | xargs echo -n > /geth/bootnodes; - if [ -s /geth/bootnodes ] - then - cat /geth/bootnodes; - exit 0; - fi; - - echo "no bootnodes found. retrying $CNT..."; - sleep 2 || break; - CNT=$((CNT+1)); -done; -echo "WARNING. unable to find bootnodes. continuing but geth may not be able to find any peers."; -exit 0; \ No newline at end of file diff --git a/packages/helm-charts/testnet/scripts/port-forward.sh b/packages/helm-charts/testnet/scripts/port-forward.sh deleted file mode 100755 index 7b36a3825..000000000 --- a/packages/helm-charts/testnet/scripts/port-forward.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Basic Usage: -# ./port-forward.sh NAME -# Specify -n NAMESPACE -r RELEASE or just pass NAME to the script and that will set NAMESPACE and RELEASE to it - -NAMESPACE="" -RELEASE="" -# Substitute _ for - because of the discrepancy between GCP and monorepo testnet names. -[ -n "$1" ] && NAMESPACE=${1/_/-} && RELEASE=${1/_/-} -while getopts ':r:n:' flag; do - case "${flag}" in - n) NAMESPACE="${OPTARG}" ;; - r) RELEASE="${OPTARG}" ;; - *) error "Unexpected option ${flag}" ;; - esac -done -[ -z "$NAMESPACE" ] && echo "Need to set the NAMESPACE_NAME via the -n flag" && exit 1; -[ -z "$RELEASE" ] && echo "Need to set RELEASE_NAME via the -r flag" && exit 1; - -kubectl port-forward --namespace $NAMESPACE $(kubectl get pods --namespace $NAMESPACE -l "app in (ethereum,testnet), component=gethminer1, release=$RELEASE" --field-selector=status.phase=Running -o jsonpath="{.items[0].metadata.name}") 8545:8545 8546:8546 diff --git a/packages/helm-charts/testnet/scripts/write-mobile-network-config.sh b/packages/helm-charts/testnet/scripts/write-mobile-network-config.sh deleted file mode 100755 index f6b17120c..000000000 --- a/packages/helm-charts/testnet/scripts/write-mobile-network-config.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Basic Usage: -# ./write-mobile-network-config.sh NAME -# Specify -n NAMESPACE -r RELEASE -t TESTNET_NAME or just pass NAME to the script and that will set NAMESPACE, RELEASE and TESTNET_NAME to it - - -NAMESPACE="" -RELEASE="" -TESTNET_NAME="" -[ -n "$1" ] && NAMESPACE=$1 && RELEASE=$1 && TESTNET_NAME=$1 -while getopts ':r:n:' flag; do - case "${flag}" in - n) NAMESPACE="${OPTARG}" ;; - r) RELEASE="${OPTARG}" ;; - t) TESTNET_NAME="${OPTARG}" ;; - *) error "Unexpected option ${flag}" ;; - esac -done -[ -z "$NAMESPACE" ] && echo "Need to set the NAMESPACE_NAME via the -n flag" && exit 1; -[ -z "$RELEASE" ] && echo "Need to set RELEASE_NAME via the -r flag" && exit 1; -[ -z "$TESTNET_NAME" ] && echo "Need to set TESTNET_NAME via the -t flag" && exit 1; - -UNDERSCORE_TESTNET_NAME="${TESTNET_NAME/-/_}" - -[ -z $(kubectl get svc --namespace $NAMESPACE $RELEASE-gethtx1 -o jsonpath='{.status.loadBalancer.ingress[0].ip}') ] && echo "Wait a minute, gethtx1 load balancer has not yet provisioned" && exit 1; - -[ -z $(kubectl get svc --namespace $NAMESPACE $RELEASE-gethtx2 -o jsonpath='{.status.loadBalancer.ingress[0].ip}') ] && echo "Wait a minute, gethtx2 load balancer has not yet provisioned" && exit 1; - -[ -z $(kubectl get svc --namespace $NAMESPACE $RELEASE-gethtx3 -o jsonpath='{.status.loadBalancer.ingress[0].ip}') ] && echo "Wait a minute, gethtx3 load balancer has not yet provisioned" && exit 1; - -[ -z $(kubectl get svc --namespace $NAMESPACE $RELEASE-gethtx4 -o jsonpath='{.status.loadBalancer.ingress[0].ip}') ] && echo "Wait a minute, gethtx4 load balancer has not yet provisioned" && exit 1; - -cat > ../mobile/src/geth/additionalNetworks.ts << EOF -export default { - '$UNDERSCORE_TESTNET_NAME': { - nodeDir: '.$UNDERSCORE_TESTNET_NAME', - enodes: [ - 'enode://$(kubectl get configmaps $NAMESPACE-geth-config -n $NAMESPACE -o jsonpath='{.data.gethtx1NodeId}')@$(kubectl get svc --namespace $NAMESPACE $RELEASE-gethtx1 -o jsonpath='{.status.loadBalancer.ingress[0].ip}'):30303', - 'enode://$(kubectl get configmaps $NAMESPACE-geth-config -n $NAMESPACE -o jsonpath='{.data.gethtx2NodeId}' - )@$(kubectl get svc --namespace $NAMESPACE $RELEASE-gethtx2 -o jsonpath='{.status.loadBalancer.ingress[0].ip}'):30303', - 'enode://$(kubectl get configmaps $NAMESPACE-geth-config -n $NAMESPACE -o jsonpath='{.data.gethtx3NodeId}')@$(kubectl get svc --namespace $NAMESPACE $RELEASE-gethtx3 -o jsonpath='{.status.loadBalancer.ingress[0].ip}'):30303', - 'enode://$(kubectl get configmaps $NAMESPACE-geth-config -n $NAMESPACE -o jsonpath='{.data.gethtx4NodeId}' - )@$(kubectl get svc --namespace $NAMESPACE $RELEASE-gethtx4 -o jsonpath='{.status.loadBalancer.ingress[0].ip}'):30303' - ], - networkID: 1101, - genesis: $(kubectl get configmaps $NAMESPACE-geth-config -n $NAMESPACE -o jsonpath="{.data['genesis\.json']}") - } -} -EOF diff --git a/packages/helm-charts/testnet/ssdstorageclass.yaml b/packages/helm-charts/testnet/ssdstorageclass.yaml deleted file mode 100644 index 142f29778..000000000 --- a/packages/helm-charts/testnet/ssdstorageclass.yaml +++ /dev/null @@ -1,8 +0,0 @@ -allowVolumeExpansion: true -apiVersion: storage.k8s.io/v1 -kind: StorageClass -metadata: - name: ssd -provisioner: kubernetes.io/gce-pd -parameters: - type: pd-ssd diff --git a/packages/helm-charts/testnet/templates/NOTES.txt b/packages/helm-charts/testnet/templates/NOTES.txt deleted file mode 100644 index adfe9d92d..000000000 --- a/packages/helm-charts/testnet/templates/NOTES.txt +++ /dev/null @@ -1 +0,0 @@ -Deployed {{ .Release.Name }}! diff --git a/packages/helm-charts/testnet/templates/_helpers.tpl b/packages/helm-charts/testnet/templates/_helpers.tpl deleted file mode 100644 index 2764475ee..000000000 --- a/packages/helm-charts/testnet/templates/_helpers.tpl +++ /dev/null @@ -1,255 +0,0 @@ -{{/* vim: set filetype=mustache: */}} - -{{- define "celo.geth-exporter-container" -}} -- name: geth-exporter - image: "{{ .Values.gethexporter.image.repository }}:{{ .Values.gethexporter.image.tag }}" - imagePullPolicy: {{ .Values.imagePullPolicy }} - ports: - - name: profiler - containerPort: 9200 - command: - - /usr/local/bin/geth_exporter - - -ipc - - /root/.celo/geth.ipc - - -filter - - (.*overall|percentiles_95) - resources: - requests: - memory: 50M - cpu: 50m - volumeMounts: - - name: data - mountPath: /root/.celo -{{- end -}} - -{{- /* This template does not define ports that will be exposed */ -}} -{{- define "celo.node-service" -}} -kind: Service -apiVersion: v1 -metadata: - name: {{ template "common.fullname" $ }}-{{ .svc_name | default .node_name }}-{{ .index }}{{ .svc_name_suffix | default "" }} - labels: - {{- include "common.standard.labels" . | nindent 4 }} - component: {{ .component_label }} -spec: - selector: - statefulset.kubernetes.io/pod-name: {{ template "common.fullname" $ }}-{{ .node_name }}-{{ .index }} - type: {{ .service_type }} - publishNotReadyAddresses: true - {{- if (eq .service_type "LoadBalancer") }} - loadBalancerIP: {{ .load_balancer_ip }} - {{- end -}} -{{- end -}} - -{{- define "celo.full-node-statefulset" -}} -apiVersion: v1 -kind: Service -metadata: - name: {{ .name }} - labels: - {{- if .proxy | default false -}} - {{- $validatorProxied := printf "%s-validators-%d" .Release.Namespace .validator_index }} - validator-proxied: "{{ $validatorProxied }}" - {{- end }} - component: {{ .component_label }} -spec: - sessionAffinity: None - ports: - - port: 8545 - name: rpc - {{- $wsPort := ((.ws_port | default .Values.geth.ws_port) | int) -}} - {{- if ne $wsPort 8545 }} - - port: {{ $wsPort }} - name: ws - {{- end }} - selector: - {{- if .proxy | default false -}} - {{- $validatorProxied := printf "%s-validators-%d" .Release.Namespace .validator_index }} - validator-proxied: "{{ $validatorProxied }}" - {{- end }} - component: {{ .component_label }} ---- -apiVersion: v1 -kind: Service -metadata: - name: {{ .name }}-headless - labels: - {{- if .proxy | default false -}} - {{- $validatorProxied := printf "%s-validators-%d" .Release.Namespace .validator_index }} - validator-proxied: "{{ $validatorProxied }}" - {{- end }} - component: {{ .component_label }} -spec: - type: ClusterIP - clusterIP: None - ports: - - port: 8545 - name: rpc - {{- if ne $wsPort 8545 }} - - port: {{ .ws_port | default .Values.geth.ws_port }} - name: ws - {{- end }} - selector: - {{- if .proxy | default false }} - {{- $validatorProxied := printf "%s-validators-%d" .Release.Namespace .validator_index }} - validator-proxied: "{{ $validatorProxied }}" - {{- end }} - component: {{ .component_label }} ---- -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: {{ template "common.fullname" . }}-{{ .name }} - labels: - {{- include "common.standard.labels" . | nindent 4 }} - component: {{ .component_label }} - {{- if .proxy | default false -}} - {{- $validatorProxied := printf "%s-validators-%d" .Release.Namespace .validator_index }} - validator-proxied: "{{ $validatorProxied }}" - {{- end }} -spec: - {{- $updateStrategy := index $.Values.updateStrategy $.component_label }} - updateStrategy: - {{- toYaml $updateStrategy | nindent 4 }} - {{- if .Values.geth.ssd_disks }} - volumeClaimTemplates: - - metadata: - name: data - {{- if .pvc_annotations }} - annotations: - {{- toYaml .pvc_annotations | nindent 8 }} - {{- end }} - spec: - storageClassName: {{ $.Values.geth.storageClass }} - accessModes: [ "ReadWriteOnce" ] - resources: - requests: - {{- $disk_size := ((eq .name "tx-nodes-private" ) | ternary .Values.geth.privateTxNodediskSizeGB .Values.geth.diskSizeGB ) }} - storage: {{ $disk_size }}Gi - {{- end }} - podManagementPolicy: Parallel - replicas: {{ .replicas }} - serviceName: {{ .name }} - selector: - matchLabels: - {{- include "common.standard.labels" . | nindent 6 }} - component: {{ .component_label }} - {{- if .proxy | default false -}} - {{- $validatorProxied := printf "%s-validators-%d" .Release.Namespace .validator_index }} - validator-proxied: "{{ $validatorProxied }}" - {{- end }} - template: - metadata: - labels: - {{- include "common.standard.labels" . | nindent 8 }} - component: {{ .component_label }} - {{- if .extraPodLabels -}} - {{- toYaml .extraPodLabels | nindent 8 }} - {{- end }} - {{- if .proxy | default false }} - {{- $validatorProxied := printf "%s-validators-%d" .Release.Namespace .validator_index }} - validator-proxied: "{{ $validatorProxied }}" - {{- end }} - {{- if .Values.metrics | default false }} - annotations: - {{- include "common.prometheus-annotations" . | nindent 8 }} - {{- end }} - spec: - initContainers: - {{- include "common.conditional-init-genesis-container" . | nindent 6 }} - {{- include "common.celotool-full-node-statefulset-container" (dict - "Values" .Values - "Release" .Release - "Chart" .Chart - "proxy" .proxy - "mnemonic_account_type" .mnemonic_account_type - "service_ip_env_var_prefix" .service_ip_env_var_prefix - "ip_addresses" .ip_addresses - "validator_index" .validator_index - ) | nindent 6 }} - {{- if .unlock | default false }} - {{- include "common.import-geth-account-container" . | nindent 6 }} - {{- end }} - containers: - {{- include "common.full-node-container" (dict - "Values" .Values - "Release" .Release - "Chart" .Chart - "proxy" .proxy - "proxy_allow_private_ip_flag" .proxy_allow_private_ip_flag - "unlock" .unlock - "rpc_apis" .rpc_apis - "expose" .expose - "syncmode" .syncmode - "gcmode" .gcmode - "resources" .resources - "ws_port" (default .Values.geth.ws_port .ws_port) - "pprof" (or (.Values.metrics) (.Values.pprof.enabled)) - "pprof_port" (.Values.pprof.port) - "light_serve" .Values.geth.light.serve - "light_maxpeers" .Values.geth.light.maxpeers - "maxpeers" .Values.geth.maxpeers - "metrics" .Values.metrics - "public_ips" .public_ips - "ethstats" (printf "%s-ethstats.%s" (include "common.fullname" .) .Release.Namespace) - "extra_setup" .extra_setup - ) | nindent 6 }} - terminationGracePeriodSeconds: {{ .Values.geth.terminationGracePeriodSeconds | default 300 }} - {{- with .affinity }} - affinity: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .node_selector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .tolerations }} - tolerations: - {{- toYaml . | nindent 8 }} - {{- end }} - volumes: - - name: data - emptyDir: {} - - name: data-shared - emptyDir: {} - - name: config - configMap: - name: {{ template "common.fullname" . }}-geth-config - - name: account - secret: - secretName: {{ template "common.fullname" . }}-geth-account -{{- end -}} - -{{- /* This template puts a semicolon-separated pair of proxy enodes into $PROXY_ENODE_URL_PAIR. */ -}} -{{- /* I.e ;. */ -}} -{{- /* Expects env variables MNEMONIC, RID (the validator index), and PROXY_INDEX */ -}} -{{- define "celo.proxyenodeurlpair" -}} -echo "Generating proxy enode url pair for proxy $PROXY_INDEX" -PROXY_INTERNAL_IP_ENV_VAR={{ $.Release.Namespace | upper }}_VALIDATORS_${RID}_PROXY_INTERNAL_${PROXY_INDEX}_SERVICE_HOST -echo "PROXY_INTERNAL_IP_ENV_VAR=$PROXY_INTERNAL_IP_ENV_VAR" -PROXY_INTERNAL_IP=`eval "echo \\${${PROXY_INTERNAL_IP_ENV_VAR}}"` -# If $PROXY_IPS is not empty, then we use the IPs from there. Otherwise, -# we use the IP address of the proxy internal service -if [ ! -z $PROXY_IPS ]; then - echo "Proxy external IP from PROXY_IPS=$PROXY_IPS: " - PROXY_EXTERNAL_IP=`echo -n $PROXY_IPS | cut -d '/' -f $((PROXY_INDEX + 1))` -else - PROXY_EXTERNAL_IP=$PROXY_INTERNAL_IP -fi -echo "Proxy internal IP: $PROXY_INTERNAL_IP" -echo "Proxy external IP: $PROXY_EXTERNAL_IP" -# Proxy key index to allow for a high number of proxies per validator without overlap -PROXY_KEY_INDEX=$(( ($RID * 10000) + $PROXY_INDEX )) -PROXY_ENODE_ADDRESS=`celotooljs.sh generate public-key --mnemonic "$MNEMONIC" --accountType proxy --index $PROXY_KEY_INDEX` -PROXY_INTERNAL_ENODE=enode://${PROXY_ENODE_ADDRESS}@${PROXY_INTERNAL_IP}:30503 -PROXY_EXTERNAL_ENODE=enode://${PROXY_ENODE_ADDRESS}@${PROXY_EXTERNAL_IP}:30303 -echo "Proxy internal enode: $PROXY_INTERNAL_ENODE" -echo "Proxy external enode: $PROXY_EXTERNAL_ENODE" -PROXY_ENODE_URL_PAIR=$PROXY_INTERNAL_ENODE\;$PROXY_EXTERNAL_ENODE -{{- end -}} - -{{- define "celo.proxyipaddresses" -}} -{{- if .Values.geth.static_ips -}} -{{- index .Values.geth.proxyIPAddressesPerValidatorArray .validatorIndex -}} -{{- end -}} -{{- end -}} diff --git a/packages/helm-charts/testnet/templates/bootnode.deployment.yaml b/packages/helm-charts/testnet/templates/bootnode.deployment.yaml deleted file mode 100644 index ab9aca550..000000000 --- a/packages/helm-charts/testnet/templates/bootnode.deployment.yaml +++ /dev/null @@ -1,101 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ template "common.fullname" . }}-bootnode - labels: - {{- include "common.standard.labels" . | nindent 4 }} - component: bootnode -spec: - strategy: - type: Recreate - replicas: 1 - selector: - matchLabels: - {{- include "common.standard.labels" . | nindent 6 }} - component: bootnode - template: - metadata: - labels: - {{- include "common.standard.labels" . | nindent 8 }} - component: bootnode - spec: - containers: - - name: bootnode - image: {{ .Values.bootnode.image.repository }}:{{ .Values.bootnode.image.tag }} - imagePullPolicy: {{ .Values.imagePullPolicy }} - command: - - /bin/sh - - -c - args: - - | - set -euo pipefail - NAT_FLAG="" - [[ "$IP_ADDRESS" != "none" ]] && NAT_FLAG="--nat=extip:$IP_ADDRESS" - /usr/local/bin/bootnode --nodekey=/etc/bootnode/node.key --writeaddress > /enode.key - exec /usr/local/bin/bootnode --nodekey=/etc/bootnode/node.key --verbosity=5 ${NAT_FLAG} --networkid=${NETWORK_ID} --ping-ip-from-packet={{ .Values.geth.ping_ip_from_packet }} - env: - - name: IP_ADDRESS - value: {{ default "none" .Values.geth.bootnodeIpAddress }} - - name: NETWORK_ID - valueFrom: - configMapKeyRef: - name: {{ template "common.fullname" . }}-geth-config - key: networkid - livenessProbe: - exec: - command: - - /bin/sh - - -c - - | - devp2p discv4 --networkid {{ .Values.genesis.networkId }} ping "enode://$(cat /enode.key)@127.0.0.1:0?discport=30301" - initialDelaySeconds: 30 - periodSeconds: 30 - volumeMounts: - {{- if not .Values.geth.overwriteBootnodePrivateKey }} - - name: data - mountPath: /etc/bootnode - {{- else }} - - name: bootnode-pkey - mountPath: /etc/bootnode - readOnly: true - {{- end }} - ports: - - name: discovery - containerPort: 30301 - protocol: UDP - {{- if not .Values.geth.overwriteBootnodePrivateKey }} - initContainers: - - name: generate-node-key - image: {{ .Values.celotool.image.repository }}:{{ .Values.celotool.image.tag }} - imagePullPolicy: {{ .Values.imagePullPolicy }} - command: - - /bin/bash - - -c - - | - celotooljs.sh generate bip32 --mnemonic "$MNEMONIC" --accountType bootnode --index 0 > /etc/bootnode/node.key - celotooljs.sh generate public-key --mnemonic "$MNEMONIC" --accountType bootnode --index 0 > /etc/bootnode/enode.key - env: - - name: MNEMONIC - valueFrom: - secretKeyRef: - name: {{ template "common.fullname" . }}-geth-account - key: mnemonic - volumeMounts: - - name: data - mountPath: /etc/bootnode - {{- end }} - volumes: - - name: data - emptyDir: {} - {{- if .Values.geth.overwriteBootnodePrivateKey }} - - name: bootnode-pkey - secret: - secretName: {{ template "common.fullname" . }}-geth-account - items: - - key: bootnodePrivateKey - path: node.key - {{- end }} - {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} diff --git a/packages/helm-charts/testnet/templates/bootnode.service.yaml b/packages/helm-charts/testnet/templates/bootnode.service.yaml deleted file mode 100644 index e8b60f032..000000000 --- a/packages/helm-charts/testnet/templates/bootnode.service.yaml +++ /dev/null @@ -1,20 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ template "common.fullname" . }}-bootnode - labels: - {{- include "common.standard.labels" . | nindent 4 }} - component: bootnode -spec: - {{- if $.Values.geth.static_ips }} - type: LoadBalancer - loadBalancerIP: {{ .Values.geth.bootnodeIpAddress }} - {{- end }} - selector: - app: {{ template "common.name" . }} - release: {{ .Release.Name }} - component: bootnode - ports: - - name: discovery - port: 30301 - protocol: UDP diff --git a/packages/helm-charts/testnet/templates/forno.ingress.yaml b/packages/helm-charts/testnet/templates/forno.ingress.yaml deleted file mode 100644 index b16d44e08..000000000 --- a/packages/helm-charts/testnet/templates/forno.ingress.yaml +++ /dev/null @@ -1,31 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: {{ .Release.Namespace }}-forno-ingress - labels: - {{- include "common.standard.labels" . | nindent 4 }} - component: forno - annotations: - kubernetes.io/tls-acme: "true" - nginx.ingress.kubernetes.io/enable-cors: "true" - # Allows WS connections to be 20 minutes long, see https://kubernetes.github.io/ingress-nginx/user-guide/miscellaneous/#websockets - nginx.ingress.kubernetes.io/proxy-read-timeout: "1200" - nginx.ingress.kubernetes.io/proxy-send-timeout: "1200" - nginx.ingress.kubernetes.io/rewrite-target: / -spec: - ingressClassName: {{ default "nginx" .Values.ingressClassName }} - tls: - - hosts: - - {{ .Release.Namespace }}-forno.{{ .Values.domain.name }}.org - secretName: {{ .Release.Namespace }}-forno-web-tls - rules: - - host: {{ .Release.Namespace }}-forno.{{ .Values.domain.name }}.org - http: - paths: - - path: /(.*) - pathType: Prefix - backend: - service: - name: tx-nodes - port: - number: 8545 diff --git a/packages/helm-charts/testnet/templates/geth-account.secret.yaml b/packages/helm-charts/testnet/templates/geth-account.secret.yaml deleted file mode 100644 index 061892390..000000000 --- a/packages/helm-charts/testnet/templates/geth-account.secret.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: {{ template "common.fullname" . }}-geth-account - labels: - {{- include "common.standard.labels" . | nindent 4 }} -type: Opaque -data: - accountSecret: {{ .Values.geth.account.secret | b64enc }} - mnemonic: {{ .Values.mnemonic | b64enc }} - {{- if .Values.geth.overwriteBootnodePrivateKey }} - bootnodePrivateKey: {{ .Values.geth.bootnodePrivateKey | b64enc }} - {{- end }} diff --git a/packages/helm-charts/testnet/templates/geth.configmap.yaml b/packages/helm-charts/testnet/templates/geth.configmap.yaml deleted file mode 100644 index 40be96e95..000000000 --- a/packages/helm-charts/testnet/templates/geth.configmap.yaml +++ /dev/null @@ -1 +0,0 @@ -{{- include "common.geth-configmap" . }} diff --git a/packages/helm-charts/testnet/templates/proxy.service.yaml b/packages/helm-charts/testnet/templates/proxy.service.yaml deleted file mode 100644 index f3c003358..000000000 --- a/packages/helm-charts/testnet/templates/proxy.service.yaml +++ /dev/null @@ -1,67 +0,0 @@ -{{- range $validatorIndex, $proxyCount := .Values.geth.proxiesPerValidator }} -{{- range $index, $e := until ($proxyCount | int) }} -{{- template "celo.node-service" (dict - "Values" $.Values - "Release" $.Release - "Chart" $.Chart - "index" $index - "service_type" "ClusterIP" - "svc_name" (print "validators-" $validatorIndex "-proxy-internal") - "node_name" (print "validators-" $validatorIndex "-proxy") - "name_suffix" "" - "component_label" "proxy" - "load_balancer_ip" "" -) }} - ports: - - name: internal-tcp - port: 30503 - protocol: TCP - - name: internal-udp - port: 30503 - protocol: UDP - {{- if not $.Values.geth.static_ips }} - - name: external-tcp - port: 30303 - protocol: TCP - - name: external-udp - port: 30303 - protocol: UDP - {{- end }} ---- -{{- if $.Values.geth.static_ips }} -{{- $proxyIpAddresses := (splitList "/" (index $.Values.geth.proxyIPAddressesPerValidatorArray $validatorIndex)) }} -{{- $loadBalancerIP := index $proxyIpAddresses $index }} -{{- template "celo.node-service" (dict - "Values" $.Values - "Release" $.Release - "Chart" $.Chart - "index" $index - "service_type" "LoadBalancer" - "node_name" (print "validators-" $validatorIndex "-proxy") - "component_label" "proxy" - "load_balancer_ip" $loadBalancerIP -) }} - ports: - - name: discovery - port: 30303 - protocol: UDP ---- -{{- template "celo.node-service" (dict - "Values" $.Values - "Release" $.Release - "Chart" $.Chart - "index" $index - "service_type" "LoadBalancer" - "node_name" (print "validators-" $validatorIndex "-proxy") - "svc_name_suffix" "-tcp" - "component_label" "proxy" - "load_balancer_ip" $loadBalancerIP -) }} - ports: - - name: celo - port: 30303 - protocol: TCP ---- -{{- end }} -{{- end }} -{{- end }} diff --git a/packages/helm-charts/testnet/templates/proxy.statefulset.yaml b/packages/helm-charts/testnet/templates/proxy.statefulset.yaml deleted file mode 100644 index 4bb8d19c9..000000000 --- a/packages/helm-charts/testnet/templates/proxy.statefulset.yaml +++ /dev/null @@ -1,29 +0,0 @@ -{{- range $validatorIndex, $proxyCount := .Values.geth.proxiesPerValidator }} -{{- include "celo.full-node-statefulset" (dict - "Values" $.Values - "Release" $.Release - "Chart" $.Chart - "name" (print "validators-" $validatorIndex "-proxy") - "component_label" "proxy" - "mnemonic_account_type" "proxy" - "replicas" $proxyCount - "proxy" true - "proxy_allow_private_ip_flag" true - "unlock" true - "expose" false - "rpc_apis" "eth,net,web3" - "syncmode" "full" - "gcmode" "full" - "resources" (default $.Values.geth.resources $.Values.geth.proxyResources) - "service_ip_env_var_prefix" (printf "%s%s%d%s" ($.Release.Namespace | upper) "_VALIDATORS_" $validatorIndex "_PROXY_INTERNAL_") - "validator_index" $validatorIndex - "ip_addresses" (include "celo.proxyipaddresses" (dict "Values" $.Values "validatorIndex" $validatorIndex) ) - "extra_setup" $.Values.geth.proxyExtraSnippet - "affinity" $.Values.geth.proxyAffinity - "node_selector" $.Values.geth.proxyNodeSelector - "tolerations" $.Values.geth.proxyTolerations - "extraPodLabels" $.Values.extraPodLabels.proxy - "pvc_annotations" $.Values.pvcAnnotations.proxy -) }} ---- -{{- end }} diff --git a/packages/helm-charts/testnet/templates/secondaries.service.yaml b/packages/helm-charts/testnet/templates/secondaries.service.yaml deleted file mode 100644 index 7c0e102c3..000000000 --- a/packages/helm-charts/testnet/templates/secondaries.service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -{{- if .Values.geth.static_ips }} -{{- range $index, $e := until (.Values.geth.secondaries | int) }} -{{- if (ge $index (len $.Values.geth.proxiesPerValidator)) }} -{{- $loadBalancerIP := index $.Values.geth.validatorsIPAddressArray $index }} -{{- template "celo.node-service" (dict "Values" $.Values "Release" $.Release "Chart" $.Chart "index" $index "service_type" "LoadBalancer" "node_name" "validators" "component_label" "validators" "load_balancer_ip" $loadBalancerIP ) }} - ports: - - name: discovery - port: 30303 - protocol: UDP ---- -{{- template "celo.node-service" (dict "Values" $.Values "Release" $.Release "Chart" $.Chart "index" $index "service_type" "LoadBalancer" "node_name" "validators" "svc_name_suffix" "-tcp" "component_label" "validators" "load_balancer_ip" $loadBalancerIP ) }} - ports: - - name: celo - port: 30303 - protocol: TCP ---- -{{- end }} -{{- end }} -{{- end }} diff --git a/packages/helm-charts/testnet/templates/secondaries.statefulset.yaml b/packages/helm-charts/testnet/templates/secondaries.statefulset.yaml deleted file mode 100644 index 2213234e9..000000000 --- a/packages/helm-charts/testnet/templates/secondaries.statefulset.yaml +++ /dev/null @@ -1,290 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: secondaries - labels: - component: secondaries -spec: - ports: - - port: 80 - name: web - clusterIP: None - selector: - component: secondaries ---- -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: {{ template "common.fullname" . }}-secondaries - labels: - {{- include "common.standard.labels" . | nindent 4 }} - component: secondaries -spec: - {{- if .Values.geth.ssd_disks }} - volumeClaimTemplates: - - metadata: - name: data - {{- if .Values.pvcAnnotations.secondary }} - annotations: - {{- toYaml .Values.pvcAnnotations.secondary | nindent 8 }} - {{- end }} - spec: - storageClassName: {{ .Values.geth.storageClass }} - accessModes: [ "ReadWriteOnce" ] - resources: - requests: - storage: {{ .Values.geth.diskSizeGB }}Gi - {{- end }} - podManagementPolicy: Parallel - updateStrategy: - {{- toYaml .Values.updateStrategy.secondaries | nindent 4 }} - replicas: {{ .Values.geth.secondaries }} - serviceName: secondaries - selector: - matchLabels: - {{- include "common.standard.labels" . | nindent 6 }} - component: secondaries - template: - metadata: - labels: - {{- include "common.standard.labels" . | nindent 8 }} - component: secondaries - {{- if .Values.extraPodLabels.secondaries }} - {{- toYaml .Values.extraPodLabels.secondaries | nindent 8 }} - {{- end }} - {{- if .Values.metrics | default false }} - annotations: - {{- include "common.prometheus-annotations" . | nindent 8 }} - {{- end }} - spec: - initContainers: - {{- include "common.conditional-init-genesis-container" . | nindent 6 }} - - name: get-account - image: {{ .Values.celotool.image.repository }}:{{ .Values.celotool.image.tag }} - imagePullPolicy: Always - command: - - /bin/bash - args: - - "-c" - - |- - [[ $REPLICA_NAME =~ -([0-9]+)$ ]] || exit 1 - RID=${BASH_REMATCH[1]} - echo -n "$RID" >/root/.celo/replica_id - echo "Generating private key for rid=$RID" - celotooljs.sh generate bip32 --mnemonic "$MNEMONIC" --accountType validator --index "$RID" > /root/.celo/pkey - echo 'Generating address' - celotooljs.sh generate account-address --private-key $(cat /root/.celo/pkey) > /root/.celo/address - - # If this is a proxied validator, it will not have an external IP address - # and EXTERNAL_IP_ADDRESS will be empty - EXTERNAL_IP_ADDRESS=$(echo -n "$IP_ADDRESSES" | cut -d '/' -f $((RID + 1))) - echo "$EXTERNAL_IP_ADDRESS" > /root/.celo/externalIpAddress - - # Put the proxies per validator array into a comma separated string - # so we can index it at runtime - PROXIES_PER_VALIDATOR="{{ join "," .Values.geth.proxiesPerValidator }}" - PROXY_COUNT=$(echo -n $PROXIES_PER_VALIDATOR | cut -d ',' -f $((RID + 1))) - echo -n "$PROXY_COUNT" > /root/.celo/proxyCount - - if [[ -z "$EXTERNAL_IP_ADDRESS" ]]; then - echo "$POD_IP" > /root/.celo/ipAddress - else - cat /root/.celo/externalIpAddress > /root/.celo/ipAddress - fi - echo -n "Generating IP address for validator: " - cat /root/.celo/ipAddress - - celotooljs.sh generate public-key --mnemonic "$MNEMONIC" --accountType bootnode --index 0 > /root/.celo/bootnodeEnodeAddress - echo -n "Generating Bootnode enode address for the validator: " - cat /root/.celo/bootnodeEnodeAddress - - [[ "$BOOTNODE_IP_ADDRESS" == 'none' ]] && BOOTNODE_IP_ADDRESS=${{ .Release.Namespace | upper }}_BOOTNODE_SERVICE_HOST - echo "enode://$(cat /root/.celo/bootnodeEnodeAddress)@$BOOTNODE_IP_ADDRESS:30301" > /root/.celo/bootnodeEnode - echo -n "Generating Bootnode enode for the validator: " - cat /root/.celo/bootnodeEnode - - # If this validator is meant to be proxied - if [[ ! -z "$PROXY_COUNT" ]]; then - # Put the all the validator's proxy IP addresses into a comma separated string - # so we can access it at runtime. Validators are separated by commas, - # and individual IP addresses are separated by /'s. For example, - # if one validator has 2 proxies, and the other has 1 proxy: - # ALL_VALIDATOR_PROXY_IPS would have the form X.X.X.X/X.X.X.X,X.X.X.X - ALL_VALIDATOR_PROXY_IPS='{{ join "," .Values.geth.proxyIPAddressesPerValidatorArray }}' - [[ $ALL_VALIDATOR_PROXY_IPS = '' ]] && ALL_VALIDATOR_PROXY_IPS='' - - PROXY_IPS=$(echo -n $ALL_VALIDATOR_PROXY_IPS | cut -d ',' -f $((RID + 1))) - - # Clear the proxy enode file because it's persisted - rm -f /root/.celo/proxyEnodeUrlPairs - # Generate all proxy enode urls and put them into /root/.celo/proxyEnodeUrlPairs - PROXY_INDEX=0 - while [ "$PROXY_INDEX" -lt "$PROXY_COUNT" ]; do - if [ "$PROXY_INDEX" -gt 0 ]; then - echo -n "," >> /root/.celo/proxyEnodeUrlPairs - fi - - # gives us PROXY_ENODE_URL_PAIR - {{- include "celo.proxyenodeurlpair" . | nindent 14 }} - echo -n $PROXY_ENODE_URL_PAIR >> /root/.celo/proxyEnodeUrlPairs - - PROXY_INDEX=$(( $PROXY_INDEX + 1 )) - done - fi - env: - - name: POD_IP - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: status.podIP - - name: REPLICA_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: MNEMONIC - valueFrom: - secretKeyRef: - name: {{ template "common.fullname" . }}-geth-account - key: mnemonic - - name: IP_ADDRESSES - value: {{ join "/" .Values.geth.validatorsIPAddressArray }} - - name: BOOTNODE_IP_ADDRESS - value: "{{ default "none" .Values.geth.bootnodeIpAddress }}" - volumeMounts: - - name: data - mountPath: /root/.celo - {{- include "common.import-geth-account-container" . | nindent 6 }} - containers: - - name: geth - image: {{ .Values.geth.image.repository }}:{{ .Values.geth.image.tag }} - imagePullPolicy: Always - command: ["/bin/sh"] - args: - - "-c" - - |- - set -euo pipefail - rm /root/.celo/pkey || true - ADDITIONAL_FLAGS='' - - ACCOUNT_ADDRESS=$(cat /root/.celo/address) - RID=$(cat /root/.celo/replica_id) - - if [ "$RID" -lt "$FAULTY_NODES" ]; then - ADDITIONAL_FLAGS="${ADDITIONAL_FLAGS} --istanbul.faultymode $FAULTY_NODE_TYPE" - fi - - if geth --help | grep 'proxy.proxyenodeurlpairs' >/dev/null; then - PROXY_FLAG="--proxy.proxyenodeurlpairs" - else - PROXY_FLAG="--proxy.proxyenodeurlpair" - fi - - PROXY_COUNT=$(cat /root/.celo/proxyCount) - if [ "$PROXY_COUNT" -gt 0 ]; then - ADDITIONAL_FLAGS="${ADDITIONAL_FLAGS} --proxy.proxied ${PROXY_FLAG}=$(cat /root/.celo/proxyEnodeUrlPairs) --nodiscover --proxy.allowprivateip" - else - ADDITIONAL_FLAGS="${ADDITIONAL_FLAGS} --ethstats=${HOSTNAME}@${ETHSTATS_SVC}" - fi - - [[ "$PING_IP_FROM_PACKET" == "true" ]] && ADDITIONAL_FLAGS="${ADDITIONAL_FLAGS} --ping-ip-from-packet" - - [[ "$IN_MEMORY_DISCOVERY_TABLE" == "true" ]] && ADDITIONAL_FLAGS="${ADDITIONAL_FLAGS} --use-in-memory-discovery-table" - - {{- include "common.bootnode-flag-script" . | nindent 10 }} - - {{- include "common.geth-add-metrics-pprof-config" . | nindent 10 }} - - {{- include "common.geth-http-ws-flags" (dict "Values" $.Values "rpc_apis" "eth,net,web3,debug" "ws_port" "8545" "listen_address" "0.0.0.0") | nindent 10 }} - - {{- .Values.geth.secondayExtraSnippet | nindent 10 }} - - exec geth \ - $BOOTNODE_FLAG \ - --datadir /root/.celo \ - --ipcpath=geth.ipc \ - --nousb \ - --password=/root/.celo/account/accountSecret \ - --unlock=${ACCOUNT_ADDRESS} \ - --mine \ - --etherbase=${ACCOUNT_ADDRESS} \ - --syncmode=full \ - --consoleformat=json \ - --consoleoutput=stdout \ - --verbosity={{ .Values.geth.verbosity }} \ - --vmodule={{ .Values.geth.vmodule }} \ - --istanbul.replica \ - --maxpeers=125 \ - --nat=extip:`cat /root/.celo/ipAddress` \ - --allow-insecure-unlock \ - ${ADDITIONAL_FLAGS} - env: - - name: POD_IP - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: status.podIP - - name: ETHSTATS_SVC - value: {{ template "common.fullname" . }}-ethstats.{{ .Release.Namespace }} - - name: NETWORK_ID - valueFrom: - configMapKeyRef: - name: {{ template "common.fullname" . }}-geth-config - key: networkid - - name: FAULTY_NODES - value: {{ .Values.geth.faultyValidators | quote }} - - name: FAULTY_NODE_TYPE - value: {{ .Values.geth.faultyValidatorType | quote }} - - name: STATIC_IPS_FOR_GETH_NODES - value: "{{ default false .Values.geth.static_ips }}" - - name: PING_IP_FROM_PACKET - value: "{{ default false .Values.geth.ping_ip_from_packet }}" - - name: IN_MEMORY_DISCOVERY_TABLE - value: "{{ default "false" .Values.geth.in_memory_discovery_table }}" - ports: - - name: discovery-udp - containerPort: 30303 - protocol: UDP - - name: discovery-tcp - containerPort: 30303 - - name: rpc - containerPort: 8545 - - name: ws - containerPort: 8546 - {{- if .Values.geth.enable_metrics | default false }} - - name: metrics - containerPort: 6060 - {{- end }} - {{- $resources := default .Values.geth.resources .Values.geth.secondaryResources -}} - {{- with $resources }} - resources: - {{- toYaml . | nindent 10 }} - {{- end }} - volumeMounts: - - name: data - mountPath: /root/.celo - - name: account - mountPath: /root/.celo/account - readOnly: true - {{- with .Values.geth.secondaryAffinity }} - affinity: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.secondayNodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.secondaryTolerations }} - tolerations: - {{- toYaml . | nindent 8 }} - {{- end }} - volumes: - - name: data - emptyDir: {} - - name: data-shared - emptyDir: {} - - name: config - configMap: - name: {{ template "common.fullname" . }}-geth-config - - name: account - secret: - secretName: {{ template "common.fullname" . }}-geth-account diff --git a/packages/helm-charts/testnet/templates/txnode-private.service.yaml b/packages/helm-charts/testnet/templates/txnode-private.service.yaml deleted file mode 100644 index 9d00ba22a..000000000 --- a/packages/helm-charts/testnet/templates/txnode-private.service.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- if .Values.geth.static_ips }} -{{- range $index, $e := until (.Values.geth.private_tx_nodes | int) }} -{{- $loadBalancerIP := default "" (index $.Values.geth (print "private_tx_nodes_" $index "IpAddress")) }} -{{- template "celo.node-service" (dict "Values" $.Values "Release" $.Release "Chart" $.Chart "index" $index "service_type" "LoadBalancer" "svc_name" "tx-nodes-private" "node_name" "tx-nodes-private" "component_label" "tx_nodes_private" "load_balancer_ip" $loadBalancerIP ) }} - ports: - - name: discovery - port: 30303 - protocol: UDP ---- -{{- template "celo.node-service" (dict "Values" $.Values "Release" $.Release "Chart" $.Chart "index" $index "service_type" "LoadBalancer" "svc_name" "tx-nodes-private" "node_name" "tx-nodes-private" "svc_name_suffix" "-tcp" "component_label" "tx_nodes_private" "load_balancer_ip" $loadBalancerIP ) }} - ports: - - name: celo - port: 30303 - protocol: TCP ---- -{{- end }} -{{- end }} diff --git a/packages/helm-charts/testnet/templates/txnode-private.statefulset.yaml b/packages/helm-charts/testnet/templates/txnode-private.statefulset.yaml deleted file mode 100644 index 2f9b5ccf0..000000000 --- a/packages/helm-charts/testnet/templates/txnode-private.statefulset.yaml +++ /dev/null @@ -1,22 +0,0 @@ -{{- include "celo.full-node-statefulset" (dict - "Values" $.Values - "Release" $.Release - "Chart" $.Chart - "name" "tx-nodes-private" - "component_label" "tx_nodes_private" - "replicas" .Values.geth.private_tx_nodes - "mnemonic_account_type" "tx_node_private" - "expose" true - "syncmode" "full" - "gcmode" "archive" - "rpc_apis" "eth,net,web3,debug,txpool" - "ws_port" "8545" - "resources" (default $.Values.geth.resources $.Values.geth.txNodePrivateResources) - "ip_addresses" (join "/" .Values.geth.private_tx_node_ip_addresses) - "extra_setup" $.Values.geth.txNodePrivateExtraSnippet - "affinity" $.Values.geth.txNodePrivateAffinity - "node_selector" $.Values.geth.txNodePrivateNodeSelector - "tolerations" $.Values.geth.txNodePrivateTolerations - "extraPodLabels" $.Values.extraPodLabels.txnode_private - "pvc_annotations" $.Values.pvcAnnotations.txnode_private -) }} diff --git a/packages/helm-charts/testnet/templates/txnode.service.yaml b/packages/helm-charts/testnet/templates/txnode.service.yaml deleted file mode 100644 index ed1656917..000000000 --- a/packages/helm-charts/testnet/templates/txnode.service.yaml +++ /dev/null @@ -1,42 +0,0 @@ -{{- range $index, $e := until (.Values.geth.tx_nodes | int) }} -{{- $loadBalancerIP := (index $.Values.geth.txNodesIPAddressArray $index) }} -{{- template "celo.node-service" (dict - "Values" $.Values - "Release" $.Release - "Chart" $.Chart - "index" $index - "service_type" "LoadBalancer" - "svc_name" "service" - "node_name" "tx-nodes" - "component_label" "tx_nodes" - "load_balancer_ip" $loadBalancerIP -) }} - ports: - - name: discovery - port: 30303 - protocol: UDP ---- -{{- template "celo.node-service" (dict - "Values" $.Values - "Release" $.Release - "Chart" $.Chart - "index" $index - "service_type" "LoadBalancer" - "svc_name" "service" - "node_name" "tx-nodes" - "svc_name_suffix" "-tcp" - "component_label" "tx_nodes" - "load_balancer_ip" $loadBalancerIP -) }} - ports: - - name: celo - port: 30303 - protocol: TCP - - name: rpc - port: 8545 - protocol: TCP - - name: ws - port: 8546 - protocol: TCP ---- -{{- end }} diff --git a/packages/helm-charts/testnet/templates/txnode.statefulset.yaml b/packages/helm-charts/testnet/templates/txnode.statefulset.yaml deleted file mode 100644 index 06a081d5c..000000000 --- a/packages/helm-charts/testnet/templates/txnode.statefulset.yaml +++ /dev/null @@ -1,22 +0,0 @@ -{{- include "celo.full-node-statefulset" (dict - "Values" $.Values - "Release" $.Release - "Chart" $.Chart - "name" "tx-nodes" - "component_label" "tx_nodes" - "replicas" .Values.geth.tx_nodes - "mnemonic_account_type" "tx_node" - "expose" true - "syncmode" "full" - "gcmode" "full" - "rpc_apis" "eth,net,web3" - "ws_port" "8545" - "resources" $.Values.geth.txNodeResources - "ip_addresses" (join "/" .Values.geth.txNodesIPAddressArray) - "extra_setup" $.Values.geth.txNodeExtraSnippet - "affinity" $.Values.geth.txNodeAffinity - "node_selector" $.Values.geth.txNodeNodeSelector - "tolerations" $.Values.geth.txNodeTolerations - "extraPodLabels" $.Values.extraPodLabels.txnode - "pvc_annotations" $.Values.pvcAnnotations.txnode -) }} diff --git a/packages/helm-charts/testnet/templates/validators.service.yaml b/packages/helm-charts/testnet/templates/validators.service.yaml deleted file mode 100644 index 995d8557c..000000000 --- a/packages/helm-charts/testnet/templates/validators.service.yaml +++ /dev/null @@ -1,38 +0,0 @@ -{{- if .Values.geth.static_ips }} -{{- range $index, $e := until (.Values.geth.validators | int) }} -{{- if (eq (index $.Values.geth.proxiesPerValidator $index | int) 0) }} -{{- $loadBalancerIP := index $.Values.geth.validatorsIPAddressArray $index }} -{{- template "celo.node-service" (dict - "Values" $.Values - "Release" $.Release - "Chart" $.Chart - "index" $index - "service_type" "LoadBalancer" - "node_name" "validators" - "component_label" "validators" - "load_balancer_ip" $loadBalancerIP -) }} - ports: - - name: discovery - port: 30303 - protocol: UDP ---- -{{- template "celo.node-service" (dict - "Values" $.Values - "Release" $.Release - "Chart" $.Chart - "index" $index - "service_type" "LoadBalancer" - "node_name" "validators" - "svc_name_suffix" "-tcp" - "component_label" "validators" - "load_balancer_ip" $loadBalancerIP -) }} - ports: - - name: celo - port: 30303 - protocol: TCP ---- -{{- end }} -{{- end }} -{{- end }} diff --git a/packages/helm-charts/testnet/templates/validators.statefulset.yaml b/packages/helm-charts/testnet/templates/validators.statefulset.yaml deleted file mode 100644 index 9b203c60f..000000000 --- a/packages/helm-charts/testnet/templates/validators.statefulset.yaml +++ /dev/null @@ -1,301 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: validators - labels: - component: validators -spec: - ports: - - port: 80 - name: web - clusterIP: None - selector: - component: validators ---- -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: {{ template "common.fullname" . }}-validators - labels: - {{- include "common.standard.labels" . | nindent 4 }} - component: validators -spec: - {{- if .Values.geth.ssd_disks }} - volumeClaimTemplates: - - metadata: - name: data - {{- if .Values.pvcAnnotations.validator }} - annotations: - {{- toYaml .Values.pvcAnnotations.validator | nindent 8 }} - {{- end }} - spec: - storageClassName: {{ .Values.geth.storageClass }} - accessModes: [ "ReadWriteOnce" ] - resources: - requests: - storage: {{ .Values.geth.diskSizeGB }}Gi - {{- end }} - podManagementPolicy: Parallel - {{- with .Values.updateStrategy.validators }} - updateStrategy: - {{- toYaml . | nindent 4 }} - {{- end }} - replicas: {{ .Values.geth.validators }} - serviceName: validators - selector: - matchLabels: - {{- include "common.standard.labels" . | nindent 6 }} - component: validators - template: - metadata: - labels: - {{- include "common.standard.labels" . | nindent 8 }} - component: validators - {{- if .Values.extraPodLabels.validators }} - {{- toYaml .Values.extraPodLabels.validators | nindent 8 }} - {{- end }} - {{- if .Values.metrics | default false }} - annotations: - {{- include "common.prometheus-annotations" . | nindent 8 }} - {{- end }} - spec: - initContainers: - {{- include "common.conditional-init-genesis-container" . | nindent 6 }} - - name: get-account - image: {{ .Values.celotool.image.repository }}:{{ .Values.celotool.image.tag }} - imagePullPolicy: Always - command: - - /bin/bash - - "-c" - args: - - | - [[ $REPLICA_NAME =~ -([0-9]+)$ ]] || exit 1 - RID=${BASH_REMATCH[1]} - echo -n "$RID" >/root/.celo/replica_id - echo "Generating private key for rid=$RID" - celotooljs.sh generate bip32 --mnemonic "$MNEMONIC" --accountType validator --index "$RID" > /root/.celo/pkey - echo 'Generating address' - celotooljs.sh generate account-address --private-key `cat /root/.celo/pkey` > /root/.celo/address - - # If this is a proxied validator, it will not have an external IP address - # and EXTERNAL_IP_ADDRESS will be empty - EXTERNAL_IP_ADDRESS=`echo -n "$IP_ADDRESSES" | cut -d '/' -f $((RID + 1))` - echo "$EXTERNAL_IP_ADDRESS" > /root/.celo/externalIpAddress - - # Put the proxies per validator array into a comma separated string - # so we can index it at runtime - PROXIES_PER_VALIDATOR="{{ join "," .Values.geth.proxiesPerValidator }}" - PROXY_COUNT=`echo -n $PROXIES_PER_VALIDATOR | cut -d ',' -f $((RID + 1))` - echo -n "$PROXY_COUNT" > /root/.celo/proxyCount - - if [[ -z "$EXTERNAL_IP_ADDRESS" ]]; then - echo "$POD_IP" > /root/.celo/ipAddress - else - cat /root/.celo/externalIpAddress > /root/.celo/ipAddress - fi - echo -n "Generating IP address for validator: " - cat /root/.celo/ipAddress - - celotooljs.sh generate public-key --mnemonic "$MNEMONIC" --accountType bootnode --index 0 > /root/.celo/bootnodeEnodeAddress - echo -n "Generating Bootnode enode address for the validator: " - cat /root/.celo/bootnodeEnodeAddress - - [[ "$BOOTNODE_IP_ADDRESS" == 'none' ]] && BOOTNODE_IP_ADDRESS=${{ .Release.Namespace | upper }}_BOOTNODE_SERVICE_HOST - echo "enode://$(cat /root/.celo/bootnodeEnodeAddress)@$BOOTNODE_IP_ADDRESS:30301" > /root/.celo/bootnodeEnode - echo -n "Generating Bootnode enode for the validator: " - cat /root/.celo/bootnodeEnode - - # Generate a fee recipient address if available - if celotooljs.sh generate address-from-env --help | grep tx_fee_recipient >/dev/null; then - celotooljs.sh generate account-address --mnemonic "$MNEMONIC" --accountType tx_fee_recipient --index $RID > /root/.celo/feeRecipientAddress - fi - - # If this validator is meant to be proxied - if [[ ! -z "$PROXY_COUNT" ]]; then - # Put the all the validator's proxy IP addresses into a comma separated string - # so we can access it at runtime. Validators are separated by commas, - # and individual IP addresses are separated by /'s. For example, - # if one validator has 2 proxies, and the other has 1 proxy: - # ALL_VALIDATOR_PROXY_IPS would have the form X.X.X.X/X.X.X.X,X.X.X.X - ALL_VALIDATOR_PROXY_IPS='{{ join "," .Values.geth.proxyIPAddressesPerValidatorArray }}' - [[ $ALL_VALIDATOR_PROXY_IPS = '' ]] && ALL_VALIDATOR_PROXY_IPS='' - PROXY_IPS=`echo -n $ALL_VALIDATOR_PROXY_IPS | cut -d ',' -f $((RID + 1))` - # Clear the proxy enode file because it's persisted - rm -f /root/.celo/proxyEnodeUrlPairs - # Generate all proxy enode urls and put them into /root/.celo/proxyEnodeUrlPairs - PROXY_INDEX=0 - while [ "$PROXY_INDEX" -lt "$PROXY_COUNT" ]; do - if [ "$PROXY_INDEX" -gt 0 ]; then - echo -n "," >> /root/.celo/proxyEnodeUrlPairs - fi - # gives us PROXY_ENODE_URL_PAIR - {{- include "celo.proxyenodeurlpair" . | nindent 14 }} - echo -n $PROXY_ENODE_URL_PAIR >> /root/.celo/proxyEnodeUrlPairs - PROXY_INDEX=$(( $PROXY_INDEX + 1 )) - done - fi - env: - - name: POD_IP - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: status.podIP - - name: REPLICA_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: MNEMONIC - valueFrom: - secretKeyRef: - name: {{ template "common.fullname" . }}-geth-account - key: mnemonic - - name: IP_ADDRESSES - value: {{ join "/" .Values.geth.validatorsIPAddressArray }} - - name: BOOTNODE_IP_ADDRESS - value: "{{ default "none" .Values.geth.bootnodeIpAddress }}" - volumeMounts: - - name: data - mountPath: /root/.celo - {{- include "common.import-geth-account-container" . | nindent 6 }} - containers: - - name: geth - image: {{ .Values.geth.image.repository }}:{{ .Values.geth.image.tag }} - imagePullPolicy: Always - command: ["/bin/sh"] - args: - - "-c" - - |- - set -euo pipefail - rm /root/.celo/pkey || true - ADDITIONAL_FLAGS='' - - ACCOUNT_ADDRESS=$(cat /root/.celo/address) - RID=$(cat /root/.celo/replica_id) - - if [ "$RID" -lt "$FAULTY_NODES" ]; then - ADDITIONAL_FLAGS="${ADDITIONAL_FLAGS} --istanbul.faultymode $FAULTY_NODE_TYPE" - fi - - if geth --help | grep 'proxy.proxyenodeurlpairs' >/dev/null; then - PROXY_FLAG="--proxy.proxyenodeurlpairs" - else - PROXY_FLAG="--proxy.proxyenodeurlpair" - fi - - PROXY_COUNT=$(cat /root/.celo/proxyCount) - if [ "$PROXY_COUNT" -gt 0 ]; then - ADDITIONAL_FLAGS="${ADDITIONAL_FLAGS} --proxy.proxied ${PROXY_FLAG}=$(cat /root/.celo/proxyEnodeUrlPairs) --nodiscover --proxy.allowprivateip" - else - ADDITIONAL_FLAGS="${ADDITIONAL_FLAGS} --ethstats=${HOSTNAME}@${ETHSTATS_SVC}" - ADDITIONAL_FLAGS="${ADDITIONAL_FLAGS} --light.maxpeers=1000 --maxpeers=1200" - fi - - [[ "$PING_IP_FROM_PACKET" == "true" ]] && ADDITIONAL_FLAGS="${ADDITIONAL_FLAGS} --ping-ip-from-packet" - - [[ "$IN_MEMORY_DISCOVERY_TABLE" == "true" ]] && ADDITIONAL_FLAGS="${ADDITIONAL_FLAGS} --use-in-memory-discovery-table" - - # Use a different fee recipient address if option available - set +e - geth --help | grep 'tx-fee-recipient' >/dev/null - tx_fee_available=$? - set -e - if [ $tx_fee_available -eq 0 ] && [ -f /root/.celo/feeRecipientAddress ] ; then - ADDITIONAL_FLAGS="${ADDITIONAL_FLAGS} --miner.validator ${ACCOUNT_ADDRESS}" - ADDITIONAL_FLAGS="${ADDITIONAL_FLAGS} --tx-fee-recipient $(cat /root/.celo/feeRecipientAddress)" - else - ADDITIONAL_FLAGS="${ADDITIONAL_FLAGS} --etherbase=${ACCOUNT_ADDRESS}" - fi - - {{- include "common.bootnode-flag-script" . | nindent 10 }} - {{- include "common.geth-add-metrics-pprof-config" . | nindent 10 }} - {{- include "common.geth-http-ws-flags" (dict "Values" $.Values "rpc_apis" "eth,net,web3,debug" "ws_port" "8545" "listen_address" "0.0.0.0") | nindent 10 }} - - {{- .Values.geth.validatorExtraSnippet | nindent 10 }} - exec geth \ - $BOOTNODE_FLAG \ - --datadir /root/.celo \ - --ipcpath=geth.ipc \ - --nousb \ - --password=/root/.celo/account/accountSecret \ - --unlock=${ACCOUNT_ADDRESS} \ - --mine \ - --syncmode=full \ - --consoleformat=json \ - --consoleoutput=stdout \ - --verbosity={{ .Values.geth.verbosity }} \ - --vmodule={{ .Values.geth.vmodule }} \ - --nat=extip:`cat /root/.celo/ipAddress` \ - --allow-insecure-unlock \ - ${ADDITIONAL_FLAGS} - env: - - name: POD_IP - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: status.podIP - - name: ETHSTATS_SVC - value: {{ template "common.fullname" . }}-ethstats.{{ .Release.Namespace }} - - name: NETWORK_ID - valueFrom: - configMapKeyRef: - name: {{ template "common.fullname" . }}-geth-config - key: networkid - - name: FAULTY_NODES - value: {{ .Values.geth.faultyValidators | quote }} - - name: FAULTY_NODE_TYPE - value: {{ .Values.geth.faultyValidatorType | quote }} - - name: STATIC_IPS_FOR_GETH_NODES - value: "{{ default false .Values.geth.static_ips }}" - - name: PING_IP_FROM_PACKET - value: "{{ default false .Values.geth.ping_ip_from_packet }}" - - name: IN_MEMORY_DISCOVERY_TABLE - value: "{{ default "false" .Values.geth.in_memory_discovery_table }}" - ports: - - name: discovery-udp - containerPort: 30303 - protocol: UDP - - name: discovery-tcp - containerPort: 30303 - - name: rpc - containerPort: 8545 - - name: ws - containerPort: 8546 - {{- if .Values.geth.enable_metrics | default false }} - - name: metrics - containerPort: 6060 - {{- end }} - {{- $resources := default .Values.geth.resources .Values.geth.validatorResources -}} - {{- with $resources }} - resources: - {{- toYaml . | nindent 10 }} - {{- end }} - volumeMounts: - - name: data - mountPath: /root/.celo - - name: account - mountPath: /root/.celo/account - readOnly: true - terminationGracePeriodSeconds: {{ .Values.geth.terminationGracePeriodSeconds | default 300 }} - {{- with .Values.geth.validatorAffinity }} - affinity: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.geth.validatorNodeSelector }} - nodeSelector: - {{ toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.geth.validatorTolerations }} - tolerations: - {{ toYaml . | nindent 8 }} - {{- end }} - volumes: - - name: data - emptyDir: {} - - name: data-shared - emptyDir: {} - - name: config - configMap: - name: {{ template "common.fullname" . }}-geth-config - - name: account - secret: - secretName: {{ template "common.fullname" . }}-geth-account diff --git a/packages/helm-charts/testnet/values-alfajores.yaml b/packages/helm-charts/testnet/values-alfajores.yaml deleted file mode 100644 index 1ae0dcf88..000000000 --- a/packages/helm-charts/testnet/values-alfajores.yaml +++ /dev/null @@ -1,81 +0,0 @@ ---- -geth: - resources: - requests: - cpu: 400m - memory: 3Gi - validatorResources: - requests: - cpu: 0.2 - memory: 3G - txNodeResources: - requests: - cpu: 0.4 - memory: 9G - txNodePrivateResources: - requests: - cpu: 1.7 - memory: 4Gi - validatorAffinity: - nodeAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 100 - preference: - matchExpressions: - - key: node.kubernetes.io/instance-type - operator: In - values: - - n2-highmem-2 - podAntiAffinity: {} - # preferredDuringSchedulingIgnoredDuringExecution: - # - weight: 100 - # podAffinityTerm: - # labelSelector: - # matchExpressions: - # - key: component - # operator: In - # values: - # - validators - # topologyKey: kubernetes.io/hostname - txNodeAffinity: - nodeAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 99 - preference: - matchExpressions: - - key: node.kubernetes.io/instance-type - operator: In - values: - - n2-highmem-2 - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 100 - podAffinityTerm: - labelSelector: - matchExpressions: - - key: component - operator: In - values: - - tx_nodes - topologyKey: kubernetes.io/hostname - txNodePrivateAffinity: - nodeAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 100 - preference: - matchExpressions: - - key: node.kubernetes.io/instance-type - operator: In - values: - - n2-highcpu-8 - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 99 - podAffinityTerm: - labelSelector: - matchExpressions: - - key: component - operator: In - values: - - tx_nodes_private - topologyKey: kubernetes.io/hostname diff --git a/packages/helm-charts/testnet/values.yaml b/packages/helm-charts/testnet/values.yaml deleted file mode 100644 index 3c2ad7ad1..000000000 --- a/packages/helm-charts/testnet/values.yaml +++ /dev/null @@ -1,141 +0,0 @@ -# Default values for ethereum. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -imagePullPolicy: Always - -# Node labels for pod assignment -# ref: https://kubernetes.io/docs/user-guide/node-selection/ -nodeSelector: {} - -bootnode: - image: - repository: us.gcr.io/celo-testnet/geth-all - tag: fc254b550a4993956ac7aa3fcd8dd4db63b8c9d2 - -celotool: - image: - repository: gcr.io/celo-testnet/celo-monorepo - tag: celotool-dc5e5dfa07231a4ff4664816a95eae606293eae9 - -genesis: - networkId: 1110 - network: testnet - useGenesisFileBase64: true - genesisFileBase64: "" - -geth: - image: - repository: us.gcr.io/celo-testnet/geth - tag: fc254b550a4993956ac7aa3fcd8dd4db63b8c9d2 - resources: - requests: - memory: "256Mi" - cpu: "500m" - limits: {} - # limits: - # memory: "4Gi" - # cpu: "4" - validatorResources: {} - secondaryResources: {} - proxyResources: {} - txNodeResources: {} - txNodePrivateResources: {} - ws_port: 8546 - rpc_gascap: 10000000 - validatorExtraSnippet: | - echo "Validator" - secondayExtraSnippet: | - echo "secondary-validator" - proxyExtraSnippet: | - echo "Proxy" - txNodeExtraSnippet: | - echo "txnode" - txNodePrivateExtraSnippet: | - echo "txnode-private" - ADDITIONAL_FLAGS="${ADDITIONAL_FLAGS} --http.timeout.read 600 --http.timeout.write 600 --http.timeout.idle 2400" - validatorAffinity: {} - validatorNodeSelector: {} - validatorTolerations: [] - secondaryAffinity: {} - secondaryNodeSelector: {} - secondaryTolerations: [] - proxyAffinity: {} - proxyNodeSelector: {} - proxyTolerations: [] - txNodeAffinity: {} - txNodeNodeSelector: {} - txNodeTolerations: [] - txNodePrivateAffinity: {} - txNodePrivateNodeSelector: {} - txNodePrivateTolerations: [] - storageClass: ssd - maxpeers: 1150 - light: - maxpeers: 1000 - serve: 70 - -# UpdateStrategy for statefulsets only. Partition=0 is default rollingUpdate behaviour. -updateStrategy: - validators: - type: RollingUpdate - rollingUpdate: - partition: 0 - secondaries: - type: RollingUpdate - rollingUpdate: - partition: 0 - proxy: - type: RollingUpdate - rollingUpdate: - partition: 0 - tx_nodes: - type: RollingUpdate - rollingUpdate: - partition: 0 - tx_nodes_private: - type: RollingUpdate - rollingUpdate: - partition: 0 - -gethexporter: - image: - repository: gcr.io/celo-testnet/geth-exporter - tag: ed7d21bd50592709173368cd697ef73c1774a261 - -blockscout: - image: - repository: gcr.io/celo-testnet/blockscout - webTag: web - indexerTag: indexer - db: - # ip: must be provided at runtime # IP address of the postgres DB - # connection_name: must be provided at runtime # name of the cloud sql connection - # username: blockscout - # password: password - name: blockscout - -domain: - name: celo-networks-dev - -ingressClassName: nginx - -extraPodLabels: - validator: - mode: full - secondary: - mode: full - proxy: - mode: full - txnode: - mode: full - txnode_private: - stack: blockscout - mode: archive - -pvcAnnotations: - validator: {} - secondary: {} - proxy: {} - txnode: {} - txnode_private: {} diff --git a/packages/helm-charts/tracer-tool/Chart.yaml b/packages/helm-charts/tracer-tool/Chart.yaml deleted file mode 100644 index 72305665c..000000000 --- a/packages/helm-charts/tracer-tool/Chart.yaml +++ /dev/null @@ -1,8 +0,0 @@ -name: tracer-tool -version: 0.0.1 -description: Chart which runs tracer tool -keywords: -- ethereum -- blockchain -- tracer -appVersion: v1.7.3 diff --git a/packages/helm-charts/tracer-tool/scripts/run.sh b/packages/helm-charts/tracer-tool/scripts/run.sh deleted file mode 100644 index acda36c5a..000000000 --- a/packages/helm-charts/tracer-tool/scripts/run.sh +++ /dev/null @@ -1,29 +0,0 @@ -FIRST_ACCOUNT="0x4da58d267cd465b9313fdb19b120ec591d957ad2"; -SECOND_ACCOUNT="0xc70947239385c2422866e20b6cafffa29157e4b3"; -CELOTOOL="/celo-monorepo/packages/celotool/bin/celotooljs.sh"; -GETH_DIR="/celo-monorepo/node_modules/@celo/geth"; -DATA_DIR="/geth-data"; -ENV_NAME="$(cat /root/envname)" - -wget https://dl.google.com/go/go1.11.5.linux-amd64.tar.gz; -tar xf go1.11.5.linux-amd64.tar.gz -C /tmp; -PATH=$PATH:/tmp/go/bin; - -cd "/celo-monorepo" && yarn run build-sdk $ENV_NAME; - -mkdir $DATA_DIR; - -$CELOTOOL geth build --geth-dir $GETH_DIR -c && -$CELOTOOL geth init --geth-dir $GETH_DIR --data-dir $DATA_DIR -e $ENV_NAME --genesis "/geth/genesis.json" --fetch-static-nodes-from-network=false; - -cat /root/pk2740 >> $DATA_DIR/keystore/UTC--2019-03-02T04-27-40.724063000Z--c70947239385c2422866e20b6cafffa29157e4b3; -cat /root/pk2745 >> $DATA_DIR/keystore/UTC--2019-03-02T04-27-45.410695000Z--4da58d267cd465b9313fdb19b120ec591d957ad2; -cat /root/staticnodes >> $DATA_DIR/static-nodes.json; - -echo "Running geth..."; - -$CELOTOOL geth run --geth-dir $GETH_DIR --data-dir $DATA_DIR --sync-mode ultralight --verbosity 1 & - -sleep 15; - -$CELOTOOL geth trace $FIRST_ACCOUNT $SECOND_ACCOUNT --data-dir $DATA_DIR -e $ENV_NAME diff --git a/packages/helm-charts/tracer-tool/templates/tracer-tool.cronjob.yaml b/packages/helm-charts/tracer-tool/templates/tracer-tool.cronjob.yaml deleted file mode 100644 index 6d32b64d4..000000000 --- a/packages/helm-charts/tracer-tool/templates/tracer-tool.cronjob.yaml +++ /dev/null @@ -1,42 +0,0 @@ -apiVersion: batch/v1beta1 -kind: CronJob -metadata: - name: {{ .Values.environment }}-tracer-tool - labels: - app: tracer-tool - chart: tracer-tool - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - component: tracer-tool -spec: - schedule: "*/5 * * * *" - concurrencyPolicy: Forbid - jobTemplate: - spec: - backoffLimit: 1 - replicas: 1 - template: - spec: - containers: - - name: tracer-tool - image: {{ .Values.imageRepository }}:{{ .Values.imageTag }} - imagePullPolicy: {{ .Values.imagePullPolicy }} - command: ["/bin/bash"] - args: ["-c", '{{ .Files.Get "scripts/run.sh" }}', "{{ .Values.environment }}"] - resources: - requests: - memory: 1G - cpu: 300m - volumeMounts: - - name: starting-files - mountPath: /root - - name: geth-config - mountPath: /geth - volumes: - - name: starting-files - configMap: - name: {{ .Values.environment }}-tracer-tool-config - - name: geth-config - configMap: - name: {{ .Values.environment }}-geth-config - restartPolicy: Never diff --git a/packages/helm-charts/tracer-tool/templates/tracer.configmap.yaml b/packages/helm-charts/tracer-tool/templates/tracer.configmap.yaml deleted file mode 100644 index 18cd3085b..000000000 --- a/packages/helm-charts/tracer-tool/templates/tracer.configmap.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ .Values.environment }}-tracer-tool-config - labels: - app: tracer-tool - chart: tracer-tool - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - component: tracer-tool -data: - envname: {{ .Values.environment }} - staticnodes: |- - {{ .Values.enodes | b64dec }} - pk2740: |- - {"address":"c70947239385c2422866e20b6cafffa29157e4b3","crypto":{"cipher":"aes-128-ctr","ciphertext":"d39cfef5d85d61972410720b2769f716db3daa19c58b6884a5afe57a99138d17","cipherparams":{"iv":"48af2b5f12455782e8494c42cbd8e7f6"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"2b8f7f1b33b495ab8500d1e84aef63888c284aa8ee34d6203a88594b4d3a0246"},"mac":"0e7446c44056f6afa5a47978371cd75a1f9e6cb34a71a8c8b2d8b73405be4614"},"id":"7cd8dd56-1996-485b-ac6a-b6e508f40355","version":3} - pk2745: |- - {"address":"4da58d267cd465b9313fdb19b120ec591d957ad2","crypto":{"cipher":"aes-128-ctr","ciphertext":"f09751814fc90ce684c83c5197e9c0588bcececa4e02dedad8acd9a9a0b27b33","cipherparams":{"iv":"82d833b076e3a7be6c6c366cad39f31d"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"3c19137687ca4f0a3b09df901553f68c08e95b6c5e06d7aee7706574840c0348"},"mac":"1f4bcf6b0be9d77a2e451cfe77ca6d6ba5871d99b4d4ee19b084c3e15cade5f8"},"id":"e6721754-3f34-44f5-a2b9-221edb67b4b1","version":3} diff --git a/packages/helm-charts/tracer-tool/values.yaml b/packages/helm-charts/tracer-tool/values.yaml deleted file mode 100644 index d4289f1a1..000000000 --- a/packages/helm-charts/tracer-tool/values.yaml +++ /dev/null @@ -1 +0,0 @@ -imagePullPolicy: IfNotPresent diff --git a/packages/helm-charts/transaction-metrics-exporter/Chart.yaml b/packages/helm-charts/transaction-metrics-exporter/Chart.yaml deleted file mode 100644 index 30477922b..000000000 --- a/packages/helm-charts/transaction-metrics-exporter/Chart.yaml +++ /dev/null @@ -1,10 +0,0 @@ -name: transaction-metrics-exporter -version: 0.0.1 -description: A small chart that runs our exporter for transaction metrics -keywords: -- blockchain -- prometheus -home: https://github.com/celo-org/celo-monorepo/packages/transaction-metrics-exporter -sources: -- https://github.com/celo-org/celo-monorepo/packages/transaction-metrics-exporter -appVersion: v1.7.3 diff --git a/packages/helm-charts/transaction-metrics-exporter/templates/deployment.yaml b/packages/helm-charts/transaction-metrics-exporter/templates/deployment.yaml deleted file mode 100644 index 3bc523d5d..000000000 --- a/packages/helm-charts/transaction-metrics-exporter/templates/deployment.yaml +++ /dev/null @@ -1,46 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ .Values.environment }}-transaction-metrics-exporter-{{ .Values.deploymentSuffix }} - labels: - app: transaction-metrics-exporter - chart: transaction-metrics-exporter - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - component: transaction-metrics-exporter -spec: - replicas: 1 - selector: - matchLabels: - app: transaction-metrics-exporter - release: {{ .Release.Name }} - component: transaction-metrics-exporter - template: - metadata: - labels: - app: transaction-metrics-exporter - release: {{ .Release.Name }} - component: transaction-metrics-exporter - spec: - containers: - - name: transaction-metrics-exporter-{{ .Values.deploymentSuffix }} - image: {{ required "A valid image repository required!" .Values.imageRepository }}:{{ required "A valid image tag required!" .Values.imageTag }} - imagePullPolicy: {{ .Values.imagePullPolicy }} - env: - - name: WEB3_PROVIDER - value: {{ .Values.web3Provider }} - - name: FROM_BLOCK - value: "{{ .Values.fromBlock }}" - - name: TO_BLOCK - value: "{{ .Values.toBlock }}" - - name: BLOCK_INTERVAL - value: "{{ .Values.blockInterval }}" - - name: WATCH_ADDRESS - value: "{{ .Values.watchAddress }}" - ports: - - name: http - containerPort: 3000 - resources: - requests: - memory: 100M - cpu: 100m diff --git a/packages/helm-charts/transaction-metrics-exporter/values.yaml b/packages/helm-charts/transaction-metrics-exporter/values.yaml deleted file mode 100644 index 1985a13bd..000000000 --- a/packages/helm-charts/transaction-metrics-exporter/values.yaml +++ /dev/null @@ -1,3 +0,0 @@ -imagePullPolicy: IfNotPresent - -web3Provider: ws://tx-nodes:8546 diff --git a/packages/helm-charts/voting-bot/Chart.yaml b/packages/helm-charts/voting-bot/Chart.yaml deleted file mode 100644 index f173ab264..000000000 --- a/packages/helm-charts/voting-bot/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A bot that votes on validator groups -name: voting-bot -version: 0.1.0 \ No newline at end of file diff --git a/packages/helm-charts/voting-bot/templates/voting-bot.cronjob.yaml b/packages/helm-charts/voting-bot/templates/voting-bot.cronjob.yaml deleted file mode 100644 index 816e07b0f..000000000 --- a/packages/helm-charts/voting-bot/templates/voting-bot.cronjob.yaml +++ /dev/null @@ -1,45 +0,0 @@ -apiVersion: batch/v1beta1 -kind: CronJob -metadata: - name: {{ .Release.Name }} - labels: - app: voting-bot - chart: voting-bot - release: {{ .Release.Service }} - component: voting-bot -spec: - schedule: "{{ .Values.cronSchedule }}" - concurrencyPolicy: Forbid - jobTemplate: - spec: - backoffLimit: 1 - template: - spec: - containers: - - name: voting-bot - image: {{ .Values.imageRepository }}:{{ .Values.imageTag }} - imagePullPolicy: {{ .Values.imagePullPolicy }} - command: - - bash - - "-c" - - | - CELOTOOL="/celo-monorepo/packages/celotool/bin/celotooljs.sh"; - - $CELOTOOL bots auto-vote --celoProvider {{ .Values.celoProvider }} --excludedGroups {{ .Values.votingBot.excludedGroups }} - env: - - name: MNEMONIC - valueFrom: - secretKeyRef: - name: {{ .Values.environment }}-voting-bot-secrets - key: mnemonic - - name: VOTING_BOT_CHANGE_BASELINE - value: {{ .Values.votingBot.changeBaseline | quote }} - - name: VOTING_BOT_EXPLORE_PROBABILITY - value: {{ .Values.votingBot.exploreProbability | quote }} - - name: VOTING_BOT_SCORE_SENSITIVITY - value: {{ .Values.votingBot.scoreSensitivity | quote }} - - name: VOTING_BOT_WAKE_PROBABILITY - value: {{ .Values.votingBot.wakeProbability | quote }} - - name: VOTING_BOTS - value: {{ .Values.votingBot.count | quote }} - restartPolicy: Never diff --git a/packages/helm-charts/voting-bot/templates/voting-bot.secret.yaml b/packages/helm-charts/voting-bot/templates/voting-bot.secret.yaml deleted file mode 100644 index 43e568d19..000000000 --- a/packages/helm-charts/voting-bot/templates/voting-bot.secret.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: {{ .Values.environment }}-voting-bot-secrets - labels: - app: voting-bot - chart: voting-bot - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - component: voting-bot -type: Opaque -data: - mnemonic: {{ .Values.mnemonic | b64enc }} \ No newline at end of file diff --git a/packages/helm-charts/voting-bot/values.yaml b/packages/helm-charts/voting-bot/values.yaml deleted file mode 100644 index d4289f1a1..000000000 --- a/packages/helm-charts/voting-bot/values.yaml +++ /dev/null @@ -1 +0,0 @@ -imagePullPolicy: IfNotPresent diff --git a/packages/helm-charts/wallet-connect/Chart.yaml b/packages/helm-charts/wallet-connect/Chart.yaml deleted file mode 100644 index 57e76866c..000000000 --- a/packages/helm-charts/wallet-connect/Chart.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: v1 -appVersion: "0.1.0" -description: A Helm chart for Wallet Connect app -name: walletconnect -version: 0.1.0 -dependencies: -- name: redis - version: 12.8.3 - repository: https://charts.bitnami.com/bitnami diff --git a/packages/helm-charts/wallet-connect/templates/_helpers.tpl b/packages/helm-charts/wallet-connect/templates/_helpers.tpl deleted file mode 100644 index 7899e732f..000000000 --- a/packages/helm-charts/wallet-connect/templates/_helpers.tpl +++ /dev/null @@ -1,51 +0,0 @@ -{{/* -Expand the name of the chart. -*/}} -{{- define "walletconnect.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "walletconnect.fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "walletconnect.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "walletconnect.labels" -}} -helm.sh/chart: {{ include "walletconnect.chart" . }} -{{ include "walletconnect.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "walletconnect.selectorLabels" -}} -app.kubernetes.io/name: {{ include "walletconnect.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} \ No newline at end of file diff --git a/packages/helm-charts/wallet-connect/templates/wallet-connect-deployment.yaml b/packages/helm-charts/wallet-connect/templates/wallet-connect-deployment.yaml deleted file mode 100644 index 861e9637d..000000000 --- a/packages/helm-charts/wallet-connect/templates/wallet-connect-deployment.yaml +++ /dev/null @@ -1,42 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ .Release.Name }} - labels: -{{ include "walletconnect.labels" . | indent 4 }} -spec: - replicas: 1 - selector: - matchLabels: -{{ include "walletconnect.selectorLabels" . | indent 6 }} - template: - metadata: - labels: -{{ include "walletconnect.selectorLabels" . | indent 8 }} - annotations: - prometheus.io/scrape: 'true' - prometheus.io/port: '5000' - prometheus.io/path: "/metrics" - spec: - containers: - - name: walletconnect - image: {{ .Values.walletconnect.image.repository }}:{{ .Values.walletconnect.image.tag }} - imagePullPolicy: {{ .Values.walletconnect.imagePullPolicy }} - env: - - name: REDIS_URL - value: redis://{{ .Release.Name }}-redis-headless:6379/0 - - name: REDIS_PREFIX - value: walletconnect-bridge - - name: NODE_ENV - value: production - ports: - - name: http - containerPort: 5000 - resources: - requests: - cpu: 100m - memory: 250Mi - {{- with .Values.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} diff --git a/packages/helm-charts/wallet-connect/templates/wallet-connect-ingress.yaml b/packages/helm-charts/wallet-connect/templates/wallet-connect-ingress.yaml deleted file mode 100644 index b2695174f..000000000 --- a/packages/helm-charts/wallet-connect/templates/wallet-connect-ingress.yaml +++ /dev/null @@ -1,25 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: {{ .Release.Name }} - labels: -{{ include "walletconnect.labels" . | indent 4 }} - annotations: - kubernetes.io/tls-acme: "true" -spec: - ingressClassName: {{ default "nginx" .Values.ingressClassName }} - tls: - - hosts: - - {{ .Release.Name }}.{{ .Values.domain.name }}.org - secretName: {{ .Release.Name }}-tls - rules: - - host: {{ .Release.Name }}.{{ .Values.domain.name }}.org - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: {{ .Release.Name }} - port: - number: 5000 diff --git a/packages/helm-charts/wallet-connect/templates/wallet-connect-service.yaml b/packages/helm-charts/wallet-connect/templates/wallet-connect-service.yaml deleted file mode 100644 index 10c12a7ac..000000000 --- a/packages/helm-charts/wallet-connect/templates/wallet-connect-service.yaml +++ /dev/null @@ -1,14 +0,0 @@ -kind: Service -apiVersion: v1 -metadata: - name: {{ .Release.Name }} - labels: -{{ include "walletconnect.labels" . | indent 4 }} -spec: - selector: -{{ include "walletconnect.selectorLabels" . | indent 4 }} - clusterIP: None - type: {{ .Values.walletconnect.service.type }} - ports: - - port: 5000 - targetPort: http \ No newline at end of file diff --git a/packages/helm-charts/wallet-connect/values.yaml b/packages/helm-charts/wallet-connect/values.yaml deleted file mode 100644 index a6a88cb67..000000000 --- a/packages/helm-charts/wallet-connect/values.yaml +++ /dev/null @@ -1,24 +0,0 @@ -environment: - name: test - network: alfajores - cluster: - name: test-cluster - location: location - -walletconnect: - image: - repository: us.gcr.io/celo-testnet/walletconnect - tag: 1472bcaad57e3746498f7a661c42ff5cf9acaf5a - imagePullPolicy: IfNotPresent - service: - type: ClusterIP - -domain: - name: walletconnect - -redis: - cluster: - enabled: false - usePassword: false - -ingressClassName: nginx diff --git a/packages/metadata-crawler/.gitignore b/packages/metadata-crawler/.gitignore deleted file mode 100644 index 4fd586cad..000000000 --- a/packages/metadata-crawler/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -lib/ -tmp/ -.tmp/ \ No newline at end of file diff --git a/packages/metadata-crawler/CHANGELOG.md b/packages/metadata-crawler/CHANGELOG.md deleted file mode 100644 index 0d85ca35b..000000000 --- a/packages/metadata-crawler/CHANGELOG.md +++ /dev/null @@ -1,67 +0,0 @@ -# @celo/metadata-crawler - -## 0.0.4-beta.0 - -### Patch Changes - -- Updated dependencies [1c9c844cf] - - @celo/contractkit@6.0.0-beta.0 -## 0.0.4 - -### Patch Changes - -- Updated dependencies [9ab9d00eb] -- Updated dependencies [1c9c844cf] -- Updated dependencies [9ab9d00eb] - - @celo/contractkit@6.0.0 - -## 0.0.3 - -### Patch Changes - -- Updated dependencies -- Updated dependencies [679ef0c60] -- Updated dependencies [32face3d8] -- Updated dependencies [87647b46b] - - @celo/contractkit@5.2.0 - - @celo/connect@5.1.1 - - @celo/utils@5.0.6 - -## 0.0.3-beta.0 - -### Patch Changes - -- Updated dependencies -- Updated dependencies [32face3d8] -- Updated dependencies [87647b46b] - - @celo/contractkit@5.2.0-beta.0 - - @celo/connect@5.1.1-beta.0 - - @celo/utils@5.0.6-beta.0 - -## 0.0.2 - -### Patch Changes - -- Updated dependencies [d48c68afc] -- Updated dependencies [d48c68afc] -- Updated dependencies [53bbd4958] -- Updated dependencies [d48c68afc] -- Updated dependencies [53bbd4958] -- Updated dependencies [d48c68afc] - - @celo/contractkit@5.1.0 - - @celo/connect@5.1.0 - - @celo/utils@5.0.5 - -## 0.0.2-beta.0 - -### Patch Changes - -- Updated dependencies [d48c68afc] -- Updated dependencies [d48c68afc] -- Updated dependencies [53bbd4958] -- Updated dependencies [d48c68afc] -- Updated dependencies [53bbd4958] -- Updated dependencies [d48c68afc] - - @celo/contractkit@5.1.0-beta.0 - - @celo/connect@5.1.0-beta.0 - - @celo/utils@5.0.5-beta.0 diff --git a/packages/metadata-crawler/README.md b/packages/metadata-crawler/README.md deleted file mode 100644 index 4f7ad561f..000000000 --- a/packages/metadata-crawler/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# Metadata Crawler - -This package connects to Blockscout database, get all the metadata urls, -verify the metadata claims and update the database if the user claims -could be verified succesfully. - -For this package to work properly, the software must have SELECT and UPDATE -access to the Blockscout database. - - -## Build - -You can build the crawler executing: - -```bash -yarn && yarn build -``` - -## Running the crawler - -For connecting to the Blockscout is necessary to setup the following environment variables: - -```bash -export PGUSER="postgres" # Database user -export PGPASSWORD="" # Database password -export PGHOST="127.0.0.1" # Database host -export PGPORT="5432" # Database port -export PGDATABASE="blockscout" # Database name -export PROVIDER_URL="http://localhost:8545" # Provider Url -``` - -You can start the crawler executing: - -```bash -yarn dev -``` diff --git a/packages/metadata-crawler/index.d.ts b/packages/metadata-crawler/index.d.ts deleted file mode 100644 index 102dc17cf..000000000 --- a/packages/metadata-crawler/index.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module 'bunyan-debug-stream' diff --git a/packages/metadata-crawler/package.json b/packages/metadata-crawler/package.json deleted file mode 100644 index 7bf08abfe..000000000 --- a/packages/metadata-crawler/package.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "@celo/metadata-crawler", - "version": "0.0.4", - "description": "Celo metadata crawler", - "main": "index.js", - "types": "./lib/index.d.ts", - "author": "Celo", - "license": "Apache-2.0", - "homepage": "https://github.com/celo-org/celo-monorepo/tree/master/packages/metadata-crawler", - "repository": "https://github.com/celo-org/celo-monorepo/tree/master/packages/metadata-crawler", - "dependencies": { - "@celo/connect": "^5.1.1", - "@celo/contractkit": "^6.0.0", - "@celo/utils": "^5.0.6", - "@types/pg": "^7.14.3", - "bunyan": "1.8.12", - "bunyan-gke-stackdriver": "0.1.2", - "debug": "^4.1.1", - "dotenv": "^8.2.0", - "googleapis": "^39.2.0", - "pg": "^7.18.0", - "ts-node": "^10.9.1", - "web3": "1.10.0" - }, - "devDependencies": { - "@types/bunyan": "1.8.8", - "@types/dotenv": "^8.2.0", - "bunyan-debug-stream": "^2.0.0" - }, - "scripts": { - "dev": "ts-node src/crawler.ts", - "build": "tsc -b .", - "clean": "tsc -b . --clean", - "clean:all": "yarn clean && rm -rf lib" - }, - "private": true -} diff --git a/packages/metadata-crawler/src/crawler.ts b/packages/metadata-crawler/src/crawler.ts deleted file mode 100644 index bc6f8d1d1..000000000 --- a/packages/metadata-crawler/src/crawler.ts +++ /dev/null @@ -1,183 +0,0 @@ -import { Address } from '@celo/connect' -import { newKitFromWeb3 } from '@celo/contractkit' -import { ClaimTypes, IdentityMetadataWrapper } from '@celo/contractkit/lib/identity' -import { - verifyAccountClaim, - verifyDomainRecord, -} from '@celo/contractkit/lib/identity/claims/verify' -import { normalizeAddressWith0x, trimLeading0x } from '@celo/utils/lib/address' -import { concurrentMap } from '@celo/utils/lib/async' -import Logger from 'bunyan' -import { Client } from 'pg' -import Web3 from 'web3' -import { dataLogger, logger, operationalLogger } from './logger' - -const CONCURRENCY = 10 - -const PGUSER = process.env['PGUSER'] || 'postgres' -const PGPASSWORD = process.env['PGPASSWORD'] || '' -const PGHOST = process.env['PGHOST'] || '127.0.0.1' -const PGPORT = process.env['PGPORT'] || '5432' -const PGDATABASE = process.env['PGDATABASE'] || 'blockscout' -const PROVIDER_URL = process.env['PROVIDER_URL'] || 'http://localhost:8545' - -const client = new Client({ - user: PGUSER, - password: PGPASSWORD, - host: PGHOST, - port: Number(PGPORT), - database: PGDATABASE, -}) - -const kit = newKitFromWeb3(new Web3(PROVIDER_URL)) - -async function jsonQuery(query: string) { - let res = await client.query(`SELECT json_agg(t) FROM (${query}) t`) - return res.rows[0].json_agg -} - -async function createVerificationClaims( - address: string, - domain: string, - verified: boolean, - accounts: Array
-) { - await addDatabaseVerificationClaims(address, domain, verified) - await concurrentMap(CONCURRENCY, accounts, (account) => - addDatabaseVerificationClaims(account, domain, verified) - ) -} - -async function addDatabaseVerificationClaims(address: string, domain: string, verified: boolean) { - try { - const query = `INSERT INTO celo_claims (address, type, element, verified, timestamp, inserted_at, updated_at) VALUES - (decode($1, 'hex'), 'domain', $2, $3, now(), now(), now()) - ON CONFLICT (address, type, element) DO - UPDATE SET verified=$3, timestamp=now(), updated_at=now() ` - // Trim 0x to match Blockscout convention - const values = [trimLeading0x(address), domain, verified] - - await client - .query(query, values) - .catch((err) => logger.error({ err, query }, 'addDataBaseVerificationClaims error')) - .then(() => dataLogger.info({ domain, address }, 'VERIFIED_DOMAIN_CLAIM')) - } catch (err) { - logger.error({ err }, 'addDataBaseVerificationClaims error') - } -} - -async function getVerifiedAccounts(metadata: IdentityMetadataWrapper, address: Address) { - const unverifiedAccounts = metadata.filterClaims(ClaimTypes.ACCOUNT) - const accountVerification = await Promise.all( - unverifiedAccounts.map(async (claim) => ({ - claim, - verified: await verifyAccountClaim(kit, claim, address), - })) - ) - const accounts = accountVerification - .filter(({ verified }) => verified === undefined) - .map((a) => a.claim.address) - - return accounts -} - -async function getVerifiedDomains( - metadata: IdentityMetadataWrapper, - address: Address, - logger: Logger -) { - const unverifiedDomains = metadata.filterClaims(ClaimTypes.DOMAIN) - - const domainVerification = await concurrentMap(CONCURRENCY, unverifiedDomains, async (claim) => { - try { - const verificationStatus = await verifyDomainRecord(kit, claim, address) - logger.debug({ claim, verificationStatus }, `verified_domain`) - return { - claim, - verified: verificationStatus === undefined, - } - } catch (err) { - logger.error({ err, claim }) - return { - claim, - verified: false, - } - } - }) - - const domains = domainVerification.filter(({ verified }) => verified).map((_) => _.claim.domain) - - return domains -} - -async function processDomainClaimForValidator(item: { url: string; address: string }) { - const itemLogger = operationalLogger.child({ url: item.url, address: item.address }) - try { - itemLogger.debug('fetch_metadata') - const metadata = await IdentityMetadataWrapper.fetchFromURL( - await kit.contracts.getAccounts(), - item.url - ) - const verifiedAccounts = await getVerifiedAccounts(metadata, item.address) - const verifiedDomains = await getVerifiedDomains(metadata, item.address, itemLogger) - - await concurrentMap(CONCURRENCY, verifiedDomains, (domain) => - createVerificationClaims(item.address, domain, true, verifiedAccounts) - ) - - itemLogger.debug( - { - verfiedAccountClaims: verifiedAccounts.length, - verifiedDomainClaims: verifiedDomains.length, - }, - 'processDomainClaimForValidator done' - ) - } catch (err) { - itemLogger.error({ err }, 'processDomainClaimForValidator error') - } -} - -async function processDomainClaims() { - let items: { address: string; url: string }[] = await jsonQuery( - `SELECT address, url FROM celo_account WHERE url is NOT NULL ` - ) - - operationalLogger.debug({ length: items.length }, 'fetching all accounts') - - items = items || [] - items = items.map((a) => ({ - ...a, - // Addresses are stored by blockscout as just the bytes prepended with \x - address: normalizeAddressWith0x(a.address.substring(2)), - })) - - return concurrentMap(CONCURRENCY, items, (item) => processDomainClaimForValidator(item)) - .then(() => { - operationalLogger.info('Closing DB connecting and finishing') - }) - .catch((err) => { - operationalLogger.error({ err }, 'processDomainClaimForValidator error') - client.end() - process.exit(1) - }) -} - -async function main() { - operationalLogger.info({ host: PGHOST }, 'Connecting DB') - await client.connect() - - client.on('error', (err) => { - operationalLogger.error({ err }, 'Reconnecting after error') - client.connect() - }) - - await processDomainClaims() - - client.end() - process.exit(0) -} - -main().catch((err) => { - operationalLogger.error({ err }) - process.exit(1) -}) diff --git a/packages/metadata-crawler/src/env.ts b/packages/metadata-crawler/src/env.ts deleted file mode 100644 index fc8e9306b..000000000 --- a/packages/metadata-crawler/src/env.ts +++ /dev/null @@ -1,19 +0,0 @@ -import * as dotenv from 'dotenv' - -if (process.env.CONFIG) { - dotenv.config({ path: process.env.CONFIG }) -} - -export function fetchEnv(name: string): string { - if (process.env[name] === undefined || process.env[name] === '') { - console.error(`ENV var '${name}' was not defined`) - throw new Error(`ENV var '${name}' was not defined`) - } - return process.env[name] as string -} - -export function fetchEnvOrDefault(name: string, defaultValue: string): string { - return process.env[name] === undefined || process.env[name] === '' - ? defaultValue - : (process.env[name] as string) -} diff --git a/packages/metadata-crawler/src/logger.ts b/packages/metadata-crawler/src/logger.ts deleted file mode 100644 index d5a18a828..000000000 --- a/packages/metadata-crawler/src/logger.ts +++ /dev/null @@ -1,30 +0,0 @@ -import Logger, { createLogger, levelFromName, LogLevelString, stdSerializers } from 'bunyan' -// @ts-ignore -import bunyanDebugStream from 'bunyan-debug-stream' -import { createStream } from 'bunyan-gke-stackdriver' -import { fetchEnvOrDefault } from './env' - -const logLevel = fetchEnvOrDefault('LOG_LEVEL', 'debug') as LogLevelString -const logFormat = fetchEnvOrDefault('LOG_FORMAT', 'human') - -let stream: any -switch (logFormat) { - case 'stackdriver': - stream = createStream(levelFromName[logLevel]) - break - case 'json': - stream = { stream: process.stdout, level: logLevel } - break - default: - stream = { level: logLevel, stream: bunyanDebugStream() } - break -} - -export const logger: Logger = createLogger({ - name: 'metadata-crawler', - serializers: stdSerializers, - streams: [stream], -}) - -export const operationalLogger = logger.child({ logger: 'operation' }) -export const dataLogger = logger.child({ logger: 'data' }) diff --git a/packages/metadata-crawler/tsconfig.json b/packages/metadata-crawler/tsconfig.json deleted file mode 100644 index bda559804..000000000 --- a/packages/metadata-crawler/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "@celo/typescript/tsconfig.library.json", - "compilerOptions": { - "rootDir": "src", - "outDir": "lib" - }, - "include": ["src", "types/", "index.d.ts"], - "references": [{ "path": "../sdk/utils" }] -} \ No newline at end of file diff --git a/packages/protocol/.env.json b/packages/protocol/.env.json deleted file mode 100644 index 62d845b7c..000000000 --- a/packages/protocol/.env.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "celoScanApiKey": "[Celo scan api]" -} diff --git a/packages/protocol/.gitignore b/packages/protocol/.gitignore deleted file mode 100644 index 0dd6ead63..000000000 --- a/packages/protocol/.gitignore +++ /dev/null @@ -1,48 +0,0 @@ -/index.js -/index.js.map - -contractPackages.js -contractPackages.js.map - -lib/**/*.js -lib/**/*.js.map - -migrations/**/*.js -migrations/**/*.js.map - -migrations_ts/**/*.js - -scripts/**/*.js -scripts/**/*.js.map - -test/**/*.js -test/**/*.js.map - -types/**/*.js -types/**/*.js.map - -scTopics - -build -.tmp -.*.tar.gz - -types/*.js -types/contracts/* - -.0x-artifacts/* -coverage/* - -deployedGrants.json - -# Foundry -cache/ -out/ - -wagmi.config.js -wagmi.config.js.map - -abis/src-generated/ -abis/lib/ -# these are copied from contracts-08 folder for purposes of publishing to npm -contracts/0.8 diff --git a/packages/protocol/.solhint.json b/packages/protocol/.solhint.json deleted file mode 100644 index d2706dc27..000000000 --- a/packages/protocol/.solhint.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "solhint:default", - "rules": { - "compiler-fixed": false, - "function-max-lines": 70, - "indent": "off", - "max-line-length": "off" - } -} diff --git a/packages/protocol/.solhintignore b/packages/protocol/.solhintignore deleted file mode 100644 index c2658d7d1..000000000 --- a/packages/protocol/.solhintignore +++ /dev/null @@ -1 +0,0 @@ -node_modules/ diff --git a/packages/protocol/CHANGELOG.md b/packages/protocol/CHANGELOG.md deleted file mode 100644 index db8f5d700..000000000 --- a/packages/protocol/CHANGELOG.md +++ /dev/null @@ -1,50 +0,0 @@ -# @celo/protocol - -## 1.0.2 - -### Patch Changes - -- Updated dependencies [679ef0c60] -- Updated dependencies [97d5ccf43] - - @celo/connect@5.1.1 - - @celo/base@6.0.0 - - @celo/cryptographic-utils@5.0.6 - - @celo/utils@5.0.6 - - @celo/wallet-local@5.1.1 - -## 1.0.2-beta.0 - -### Patch Changes - -- Updated dependencies [97d5ccf43] - - @celo/base@6.0.0-beta.0 - - @celo/connect@5.1.1-beta.0 - - @celo/cryptographic-utils@5.0.6-beta.0 - - @celo/utils@5.0.6-beta.0 - - @celo/wallet-local@5.1.1-beta.0 - -## 1.0.1 - -### Patch Changes - -- Updated dependencies [d48c68afc] -- Updated dependencies [53bbd4958] -- Updated dependencies [53bbd4958] - - @celo/connect@5.1.0 - - @celo/wallet-local@5.1.0 - - @celo/cryptographic-utils@5.0.5 - - @celo/utils@5.0.5 - - @celo/base@5.0.5 - -## 1.0.1-beta.0 - -### Patch Changes - -- Updated dependencies [d48c68afc] -- Updated dependencies [53bbd4958] -- Updated dependencies [53bbd4958] - - @celo/connect@5.1.0-beta.0 - - @celo/wallet-local@5.1.0-beta.0 - - @celo/cryptographic-utils@5.0.5-beta.0 - - @celo/utils@5.0.5-beta.0 - - @celo/base@5.0.5-beta.0 diff --git a/packages/protocol/LICENSE b/packages/protocol/LICENSE deleted file mode 100644 index 153d416dc..000000000 --- a/packages/protocol/LICENSE +++ /dev/null @@ -1,165 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. \ No newline at end of file diff --git a/packages/protocol/README.md b/packages/protocol/README.md deleted file mode 100644 index 84b0c94e3..000000000 --- a/packages/protocol/README.md +++ /dev/null @@ -1,168 +0,0 @@ -# Protocols - -Smart contracts for the Celo protocols, including identity and stability. - -## License - -The contents of this package are licensed under the terms of the GNU Lesser Public License V3 - -### Initial deployment - -See the the [testnet helm chart README](../helm-charts/testnet/README.md) for how to expose the RPC endpoint. - -Then, to deploy contracts to a network run: - -```bash -yarn run init-network -n NETWORK -``` - -This will deploy the contracts to the network specified in `truffle-config.js` and save the artifacts to `build/NETWORK`. -If your network was deployed with `helm`, you will probably set `NETWORK` the same as your `NAME` (which sets `NAMESPACE_NAME` and `RELEASE_NAME`). For more clarity on these names, also see the [testnet helm chart README](../helm-charts/testnet/README.md) - -### Migrations - -If a new contract needs to be deployed, create a migration file in the `migrations/` directory, prefixing it with the successor of the highest current migration number. - -To apply any new migrations to a network, run: - -```bash -yarn run migrate -n NETWORK -``` - -### Accounts - -To give an account some gold, wrapped gold, and stable token, run: - -```bash -yarn run faucet -n NETWORK -a ACCOUNT_ADDRESS -``` - -You can check balances by running: - -```bash -yarn run get-balances -n NETWORK -a ACCOUNT_ADDRESS -``` - -You can run 'onlyOwner' methods via the [MultiSig](contracts/common/MultiSig.sol) by running: - -```bash -yarn run govern -n NETWORK -c "stableToken.setMinter(0x1234)" -``` - -### Build artifacts - -When interacting with one of our Kubernetes-deployed networks, you can download the build artifacts to a local directory using: - -```bash -yarn run download-artifacts -n NAME -``` - -You must run this before interacting with one of these networks to have the build artifacts available locally. - -If you changed the build artifacts (e.g. by running the `init-network`, `migrate`, or `upgrade` script), upload the new build artifacts with: - -```bash -yarn run upload-artifacts -n NAME -``` - -By default, `NAME` will be set as `RELEASE_NAME`, `NAMESPACE_NAME`, `TESTNET_NAME` which you should have used with the same name in prior instructions. If you used separate names for the above, you can customize the run with the `-r -n -t` flags respectively. - -### Console - -To start a truffle console run: -``` -yarn console -f -n rc1 -``` - -Options: -- "-f" for Forno mode, otherwise there needs to be a node running at localhost:8585 -- "-n " possible values are: "rc1", "alfajores", "baklava" - -All compiled assets from `build/contracts` are injected in scope so for example you can do: - -``` -truffle(rc1)> let exchange = await ExchangeEUR.at("0xE383394B913d7302c49F794C7d3243c429d53D1d") -``` -To instantiate a contract at a known address, and then interact with it: - -``` -truffle(rc1)> exchange.getBuyAndSellBuckets(true) -Result { - '0': , - '1': } - -``` - -Or you can use ContractKit: - -``` -truffle(rc1)> let kit = require('@celo/contractkit').newKitFromWeb3(web3) -truffle(rc1)> let exchange = await kit.contracts.getExchange() -``` - -### Testing - -To test the smart contracts, run: - -```bash -yarn run test -``` - -Adding the optional `--gas` flag will print out a report of contract gas usage. - - -To test a single smart contract, run: -```bash -yarn run test ${contract name} -``` -Adding the optional `--gas` flag will print out a report of contract gas usage. - -For quick test iterations run: -```bash -yarn run quicktest -``` - -or for a single contract: -```bash -yarn run quicktest ${contract name} -``` - -For `quicktest` to work correctly a contract's migration dependencies have to be uncommented in `scripts/bash/backupmigrations.sh`. - -Compared to the normal test command, quicktest will: -1. Not run the pretest script of building solidity (will still be run as part of truffle test) and compiling typescript. This works because truffle can run typescript "natively". -2. Only migrate selected migrations as set in `backupmigrations.sh` (you'll likely need at least one compilation step since truffle seems to only run compiled migrations) - -## Verify released smart contracts -1. Update CeloScanApi in env.json file -2. Run verification command - -```bash -yarn truffle-verify [ContractName]@[Contract address] --network [network] --forno [network rpc url] -``` - -example: -```bash -yarn truffle-verify MentoFeeHandlerSeller@0x4efa274b7e33476c961065000d58ee09f7921a74 --network mainnet --forno https://forno.celo.org -``` - -### Possible problems - 1. Some of old smart contracts have slightly different bytecode when verified (it is usually just few bytes difference). Some of the smart contracts were originally deployed with version 0.5.8 instead of 0.5.13 even though there is no history trace about this in our monorepo. - 2. Bytecode differs because of missing library addresses on CeloScan. Json file that will be manually uploaded to CeloScan needs to have libraries root element updated. Library addresses is possible to get either manually or with command which will generate libraries.json. - ```bash - yarn verify-deployed -n $NETWORK -b $PREVIOUS_RELEASE -f - ``` - - ```javascript - { - "libraries": { - "/contracts/governance/Governance.sol": { - "Proposals": "0x38afc0dc55415ae27b81c24b5a5fbfe433ebfba8", - "IntegerSortedLinkedList": "0x411b40a81a07fcd3542ce5b3d7e215178c4ca2ef", - "AddressLinkedList": "0xd26d896d258e258eba71ff0873a878ec36538f8d", - "Signatures": "0x69baecd458e7c08b13a18e11887dbb078fb3cbb4", - "AddressSortedLinkedList": "0x4819ad0a0eb1304b1d7bc3afd7818017b52a87ab" - } - } - } -``` diff --git a/packages/protocol/abis/README.md b/packages/protocol/abis/README.md deleted file mode 100644 index 240bfada4..000000000 --- a/packages/protocol/abis/README.md +++ /dev/null @@ -1,51 +0,0 @@ -# Celo core contracts ABIS - -Smart contracts ABIS for the Celo protocol. - -## Usage - -### Installation - -```bash -npm install @celo/abis -``` - -or - -```bash -yarn add @celo/abis -``` - -### In your javascript or ts - -```ts -// abi in json -import AccountsABI from '@celo/abis/Accounts.json' - -// abi in js/ts for viem, wagmi, etc -import { accountsABI } from '@celo/abis' - -// abi in js/ts for viem, wagmi, etc (with moduleResolution and module set to "Node16" in your tsconfig.json file) -import { accountsABI } from '@celo/abis/Accounts' - -// abi in js/ts for use with contractkit -import { type Accounts, newAccounts, ABI } from '@celo/abis/web3/Accounts' -``` - -### CommonJS syntax - -```js -const { accountsABI } = require('@celo/abis'); - -// viem -const accounts = getContract({ - address: "0x...", - abi: accountsABI, - ... -}) -``` - - -## License - -All packages are licensed under the terms of the Apache 2.0 License unless otherwise specified in the LICENSE file at package's root. diff --git a/packages/protocol/abis/package-cjs.json b/packages/protocol/abis/package-cjs.json deleted file mode 100644 index 5bbefffba..000000000 --- a/packages/protocol/abis/package-cjs.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "type": "commonjs" -} diff --git a/packages/protocol/abis/package-esm.json b/packages/protocol/abis/package-esm.json deleted file mode 100644 index 3dbc1ca59..000000000 --- a/packages/protocol/abis/package-esm.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "type": "module" -} diff --git a/packages/protocol/abis/package.json b/packages/protocol/abis/package.json deleted file mode 100644 index e3a8a9a8b..000000000 --- a/packages/protocol/abis/package.json +++ /dev/null @@ -1,561 +0,0 @@ -{ - "name": "@celo/abis", - "version": "10.0.0-local", - "author": "cLabs", - "license": "LGPL-3.0", - "main": "./dist/cjs/index.js", - "module": "./dist/esm/index.js", - "types": "./dist/types/index.d.ts", - "typings": "./dist/types/index.d.ts", - "repository": { - "url": "git+https://github.com/celo-org/celo-monorepo.git", - "directory": "packages/protocol/abis" - }, - "scripts": {}, - "dependencies": {}, - "peerDependencies": {}, - "files": [ - "./dist", - "!**/*.js.map" - ], - "exports": { - "./Accounts.json": { - "default": "./dist/Accounts.json" - }, - "./Attestations.json": { - "default": "./dist/Attestations.json" - }, - "./BlockchainParameters.json": { - "default": "./dist/BlockchainParameters.json" - }, - "./DoubleSigningSlasher.json": { - "default": "./dist/DoubleSigningSlasher.json" - }, - "./DowntimeSlasher.json": { - "default": "./dist/DowntimeSlasher.json" - }, - "./Election.json": { - "default": "./dist/Election.json" - }, - "./EpochRewards.json": { - "default": "./dist/EpochRewards.json" - }, - "./Escrow.json": { - "default": "./dist/Escrow.json" - }, - "./Exchange.json": { - "default": "./dist/Exchange.json" - }, - "./ExchangeBRL.json": { - "default": "./dist/ExchangeBRL.json" - }, - "./ExchangeEUR.json": { - "default": "./dist/ExchangeEUR.json" - }, - "./FederatedAttestations.json": { - "default": "./dist/FederatedAttestations.json" - }, - "./FeeCurrencyWhitelist.json": { - "default": "./dist/FeeCurrencyWhitelist.json" - }, - "./FeeHandler.json": { - "default": "./dist/FeeHandler.json" - }, - "./Freezer.json": { - "default": "./dist/Freezer.json" - }, - "./GasPriceMinimum.json": { - "default": "./dist/GasPriceMinimum.json" - }, - "./GoldToken.json": { - "default": "./dist/GoldToken.json" - }, - "./Governance.json": { - "default": "./dist/Governance.json" - }, - "./GovernanceApproverMultiSig.json": { - "default": "./dist/GovernanceApproverMultiSig.json" - }, - "./GrandaMento.json": { - "default": "./dist/GrandaMento.json" - }, - "./ICeloToken.json": { - "default": "./dist/ICeloToken.json" - }, - "./ICeloVersionedContract.json": { - "default": "./dist/ICeloVersionedContract.json" - }, - "./IERC20.json": { - "default": "./dist/IERC20.json" - }, - "./LockedGold.json": { - "default": "./dist/LockedGold.json" - }, - "./MentoFeeHandlerSeller.json": { - "default": "./dist/MentoFeeHandlerSeller.json" - }, - "./MetaTransactionWallet.json": { - "default": "./dist/MetaTransactionWallet.json" - }, - "./MetaTransactionWalletDeployer.json": { - "default": "./dist/MetaTransactionWalletDeployer.json" - }, - "./MultiSig.json": { - "default": "./dist/MultiSig.json" - }, - "./OdisPayments.json": { - "default": "./dist/OdisPayments.json" - }, - "./Proxy.json": { - "default": "./dist/Proxy.json" - }, - "./Random.json": { - "default": "./dist/Random.json" - }, - "./Registry.json": { - "default": "./dist/Registry.json" - }, - "./ReleaseGold.json": { - "default": "./dist/ReleaseGold.json" - }, - "./Reserve.json": { - "default": "./dist/Reserve.json" - }, - "./ReserveSpenderMultiSig.json": { - "default": "./dist/ReserveSpenderMultiSig.json" - }, - "./SortedOracles.json": { - "default": "./dist/SortedOracles.json" - }, - "./StableToken.json": { - "default": "./dist/StableToken.json" - }, - "./StableTokenBRL.json": { - "default": "./dist/StableTokenBRL.json" - }, - "./StableTokenEUR.json": { - "default": "./dist/StableTokenEUR.json" - }, - "./UniswapFeeHandlerSeller.json": { - "default": "./dist/UniswapFeeHandlerSeller.json" - }, - "./Validators.json": { - "default": "./dist/Validators.json" - }, - "./Accounts": { - "import": "./dist/esm/Accounts.js", - "require": "./dist/cjs/Accounts.js", - "types": "./dist/types/Accounts.d.ts" - }, - "./Attestations": { - "import": "./dist/esm/Attestations.js", - "require": "./dist/cjs/Attestations.js", - "types": "./dist/types/Attestations.d.ts" - }, - "./BlockchainParameters": { - "import": "./dist/esm/BlockchainParameters.js", - "require": "./dist/cjs/BlockchainParameters.js", - "types": "./dist/types/BlockchainParameters.d.ts" - }, - "./DoubleSigningSlasher": { - "import": "./dist/esm/DoubleSigningSlasher.js", - "require": "./dist/cjs/DoubleSigningSlasher.js", - "types": "./dist/types/DoubleSigningSlasher.d.ts" - }, - "./DowntimeSlasher": { - "import": "./dist/esm/DowntimeSlasher.js", - "require": "./dist/cjs/DowntimeSlasher.js", - "types": "./dist/types/DowntimeSlasher.d.ts" - }, - "./Election": { - "import": "./dist/esm/Election.js", - "require": "./dist/cjs/Election.js", - "types": "./dist/types/Election.d.ts" - }, - "./EpochRewards": { - "import": "./dist/esm/EpochRewards.js", - "require": "./dist/cjs/EpochRewards.js", - "types": "./dist/types/EpochRewards.d.ts" - }, - "./Escrow": { - "import": "./dist/esm/Escrow.js", - "require": "./dist/cjs/Escrow.js", - "types": "./dist/types/Escrow.d.ts" - }, - "./Exchange": { - "import": "./dist/esm/Exchange.js", - "require": "./dist/cjs/Exchange.js", - "types": "./dist/types/Exchange.d.ts" - }, - "./ExchangeBRL": { - "import": "./dist/esm/ExchangeBRL.js", - "require": "./dist/cjs/ExchangeBRL.js", - "types": "./dist/types/ExchangeBRL.d.ts" - }, - "./ExchangeEUR": { - "import": "./dist/esm/ExchangeEUR.js", - "require": "./dist/cjs/ExchangeEUR.js", - "types": "./dist/types/ExchangeEUR.d.ts" - }, - "./FederatedAttestations": { - "import": "./dist/esm/FederatedAttestations.js", - "require": "./dist/cjs/FederatedAttestations.js", - "types": "./dist/types/FederatedAttestations.d.ts" - }, - "./FeeCurrencyWhitelist": { - "import": "./dist/esm/FeeCurrencyWhitelist.js", - "require": "./dist/cjs/FeeCurrencyWhitelist.js", - "types": "./dist/types/FeeCurrencyWhitelist.d.ts" - }, - "./FeeHandler": { - "import": "./dist/esm/FeeHandler.js", - "require": "./dist/cjs/FeeHandler.js", - "types": "./dist/types/FeeHandler.d.ts" - }, - "./Freezer": { - "import": "./dist/esm/Freezer.js", - "require": "./dist/cjs/Freezer.js", - "types": "./dist/types/Freezer.d.ts" - }, - "./GasPriceMinimum": { - "import": "./dist/esm/GasPriceMinimum.js", - "require": "./dist/cjs/GasPriceMinimum.js", - "types": "./dist/types/GasPriceMinimum.d.ts" - }, - "./GoldToken": { - "import": "./dist/esm/GoldToken.js", - "require": "./dist/cjs/GoldToken.js", - "types": "./dist/types/GoldToken.d.ts" - }, - "./Governance": { - "import": "./dist/esm/Governance.js", - "require": "./dist/cjs/Governance.js", - "types": "./dist/types/Governance.d.ts" - }, - "./GovernanceApproverMultiSig": { - "import": "./dist/esm/GovernanceApproverMultiSig.js", - "require": "./dist/cjs/GovernanceApproverMultiSig.js", - "types": "./dist/types/GovernanceApproverMultiSig.d.ts" - }, - "./GrandaMento": { - "import": "./dist/esm/GrandaMento.js", - "require": "./dist/cjs/GrandaMento.js", - "types": "./dist/types/GrandaMento.d.ts" - }, - "./ICeloToken": { - "import": "./dist/esm/ICeloToken.js", - "require": "./dist/cjs/ICeloToken.js", - "types": "./dist/types/ICeloToken.d.ts" - }, - "./ICeloVersionedContract": { - "import": "./dist/esm/ICeloVersionedContract.js", - "require": "./dist/cjs/ICeloVersionedContract.js", - "types": "./dist/types/ICeloVersionedContract.d.ts" - }, - "./IERC20": { - "import": "./dist/esm/IERC20.js", - "require": "./dist/cjs/IERC20.js", - "types": "./dist/types/IERC20.d.ts" - }, - "./LockedGold": { - "import": "./dist/esm/LockedGold.js", - "require": "./dist/cjs/LockedGold.js", - "types": "./dist/types/LockedGold.d.ts" - }, - "./MentoFeeHandlerSeller": { - "import": "./dist/esm/MentoFeeHandlerSeller.js", - "require": "./dist/cjs/MentoFeeHandlerSeller.js", - "types": "./dist/types/MentoFeeHandlerSeller.d.ts" - }, - "./MetaTransactionWallet": { - "import": "./dist/esm/MetaTransactionWallet.js", - "require": "./dist/cjs/MetaTransactionWallet.js", - "types": "./dist/types/MetaTransactionWallet.d.ts" - }, - "./MetaTransactionWalletDeployer": { - "import": "./dist/esm/MetaTransactionWalletDeployer.js", - "require": "./dist/cjs/MetaTransactionWalletDeployer.js", - "types": "./dist/types/MetaTransactionWalletDeployer.d.ts" - }, - "./MultiSig": { - "import": "./dist/esm/MultiSig.js", - "require": "./dist/cjs/MultiSig.js", - "types": "./dist/types/MultiSig.d.ts" - }, - "./OdisPayments": { - "import": "./dist/esm/OdisPayments.js", - "require": "./dist/cjs/OdisPayments.js", - "types": "./dist/types/OdisPayments.d.ts" - }, - "./Proxy": { - "import": "./dist/esm/Proxy.js", - "require": "./dist/cjs/Proxy.js", - "types": "./dist/types/Proxy.d.ts" - }, - "./Random": { - "import": "./dist/esm/Random.js", - "require": "./dist/cjs/Random.js", - "types": "./dist/types/Random.d.ts" - }, - "./Registry": { - "import": "./dist/esm/Registry.js", - "require": "./dist/cjs/Registry.js", - "types": "./dist/types/Registry.d.ts" - }, - "./ReleaseGold": { - "import": "./dist/esm/ReleaseGold.js", - "require": "./dist/cjs/ReleaseGold.js", - "types": "./dist/types/ReleaseGold.d.ts" - }, - "./Reserve": { - "import": "./dist/esm/Reserve.js", - "require": "./dist/cjs/Reserve.js", - "types": "./dist/types/Reserve.d.ts" - }, - "./ReserveSpenderMultiSig": { - "import": "./dist/esm/ReserveSpenderMultiSig.js", - "require": "./dist/cjs/ReserveSpenderMultiSig.js", - "types": "./dist/types/ReserveSpenderMultiSig.d.ts" - }, - "./SortedOracles": { - "import": "./dist/esm/SortedOracles.js", - "require": "./dist/cjs/SortedOracles.js", - "types": "./dist/types/SortedOracles.d.ts" - }, - "./StableToken": { - "import": "./dist/esm/StableToken.js", - "require": "./dist/cjs/StableToken.js", - "types": "./dist/types/StableToken.d.ts" - }, - "./StableTokenBRL": { - "import": "./dist/esm/StableTokenBRL.js", - "require": "./dist/cjs/StableTokenBRL.js", - "types": "./dist/types/StableTokenBRL.d.ts" - }, - "./StableTokenEUR": { - "import": "./dist/esm/StableTokenEUR.js", - "require": "./dist/cjs/StableTokenEUR.js", - "types": "./dist/types/StableTokenEUR.d.ts" - }, - "./UniswapFeeHandlerSeller": { - "import": "./dist/esm/UniswapFeeHandlerSeller.js", - "require": "./dist/cjs/UniswapFeeHandlerSeller.js", - "types": "./dist/types/UniswapFeeHandlerSeller.d.ts" - }, - "./Validators": { - "import": "./dist/esm/Validators.js", - "require": "./dist/cjs/Validators.js", - "types": "./dist/types/Validators.d.ts" - }, - "./web3/0.8/GasPriceMinimum": { - "import": "./dist/esm/web3/0.8/GasPriceMinimum.js", - "require": "./dist/cjs/web3/0.8/GasPriceMinimum.js", - "types": "./dist/types/web3/0.8/GasPriceMinimum.d.ts" - }, - "./web3/Accounts": { - "import": "./dist/esm/web3/Accounts.js", - "require": "./dist/cjs/web3/Accounts.js", - "types": "./dist/types/web3/Accounts.d.ts" - }, - "./web3/Attestations": { - "import": "./dist/esm/web3/Attestations.js", - "require": "./dist/cjs/web3/Attestations.js", - "types": "./dist/types/web3/Attestations.d.ts" - }, - "./web3/BlockchainParameters": { - "import": "./dist/esm/web3/BlockchainParameters.js", - "require": "./dist/cjs/web3/BlockchainParameters.js", - "types": "./dist/types/web3/BlockchainParameters.d.ts" - }, - "./web3/DoubleSigningSlasher": { - "import": "./dist/esm/web3/DoubleSigningSlasher.js", - "require": "./dist/cjs/web3/DoubleSigningSlasher.js", - "types": "./dist/types/web3/DoubleSigningSlasher.d.ts" - }, - "./web3/DowntimeSlasher": { - "import": "./dist/esm/web3/DowntimeSlasher.js", - "require": "./dist/cjs/web3/DowntimeSlasher.js", - "types": "./dist/types/web3/DowntimeSlasher.d.ts" - }, - "./web3/Election": { - "import": "./dist/esm/web3/Election.js", - "require": "./dist/cjs/web3/Election.js", - "types": "./dist/types/web3/Election.d.ts" - }, - "./web3/EpochRewards": { - "import": "./dist/esm/web3/EpochRewards.js", - "require": "./dist/cjs/web3/EpochRewards.js", - "types": "./dist/types/web3/EpochRewards.d.ts" - }, - "./web3/Escrow": { - "import": "./dist/esm/web3/Escrow.js", - "require": "./dist/cjs/web3/Escrow.js", - "types": "./dist/types/web3/Escrow.d.ts" - }, - "./web3/FederatedAttestations": { - "import": "./dist/esm/web3/FederatedAttestations.js", - "require": "./dist/cjs/web3/FederatedAttestations.js", - "types": "./dist/types/web3/FederatedAttestations.d.ts" - }, - "./web3/FeeCurrencyWhitelist": { - "import": "./dist/esm/web3/FeeCurrencyWhitelist.js", - "require": "./dist/cjs/web3/FeeCurrencyWhitelist.js", - "types": "./dist/types/web3/FeeCurrencyWhitelist.d.ts" - }, - "./web3/FeeHandler": { - "import": "./dist/esm/web3/FeeHandler.js", - "require": "./dist/cjs/web3/FeeHandler.js", - "types": "./dist/types/web3/FeeHandler.d.ts" - }, - "./web3/Freezer": { - "import": "./dist/esm/web3/Freezer.js", - "require": "./dist/cjs/web3/Freezer.js", - "types": "./dist/types/web3/Freezer.d.ts" - }, - "./web3/GasPriceMinimum": { - "import": "./dist/esm/web3/GasPriceMinimum.js", - "require": "./dist/cjs/web3/GasPriceMinimum.js", - "types": "./dist/types/web3/GasPriceMinimum.d.ts" - }, - "./web3/GoldToken": { - "import": "./dist/esm/web3/GoldToken.js", - "require": "./dist/cjs/web3/GoldToken.js", - "types": "./dist/types/web3/GoldToken.d.ts" - }, - "./web3/Governance": { - "import": "./dist/esm/web3/Governance.js", - "require": "./dist/cjs/web3/Governance.js", - "types": "./dist/types/web3/Governance.d.ts" - }, - "./web3/GovernanceApproverMultiSig": { - "import": "./dist/esm/web3/GovernanceApproverMultiSig.js", - "require": "./dist/cjs/web3/GovernanceApproverMultiSig.js", - "types": "./dist/types/web3/GovernanceApproverMultiSig.d.ts" - }, - "./web3/ICeloToken": { - "import": "./dist/esm/web3/ICeloToken.js", - "require": "./dist/cjs/web3/ICeloToken.js", - "types": "./dist/types/web3/ICeloToken.d.ts" - }, - "./web3/ICeloVersionedContract": { - "import": "./dist/esm/web3/ICeloVersionedContract.js", - "require": "./dist/cjs/web3/ICeloVersionedContract.js", - "types": "./dist/types/web3/ICeloVersionedContract.d.ts" - }, - "./web3/IERC20": { - "import": "./dist/esm/web3/IERC20.js", - "require": "./dist/cjs/web3/IERC20.js", - "types": "./dist/types/web3/IERC20.d.ts" - }, - "./web3/LockedGold": { - "import": "./dist/esm/web3/LockedGold.js", - "require": "./dist/cjs/web3/LockedGold.js", - "types": "./dist/types/web3/LockedGold.d.ts" - }, - "./web3/MentoFeeHandlerSeller": { - "import": "./dist/esm/web3/MentoFeeHandlerSeller.js", - "require": "./dist/cjs/web3/MentoFeeHandlerSeller.js", - "types": "./dist/types/web3/MentoFeeHandlerSeller.d.ts" - }, - "./web3/MetaTransactionWallet": { - "import": "./dist/esm/web3/MetaTransactionWallet.js", - "require": "./dist/cjs/web3/MetaTransactionWallet.js", - "types": "./dist/types/web3/MetaTransactionWallet.d.ts" - }, - "./web3/MetaTransactionWalletDeployer": { - "import": "./dist/esm/web3/MetaTransactionWalletDeployer.js", - "require": "./dist/cjs/web3/MetaTransactionWalletDeployer.js", - "types": "./dist/types/web3/MetaTransactionWalletDeployer.d.ts" - }, - "./web3/MultiSig": { - "import": "./dist/esm/web3/MultiSig.js", - "require": "./dist/cjs/web3/MultiSig.js", - "types": "./dist/types/web3/MultiSig.d.ts" - }, - "./web3/OdisPayments": { - "import": "./dist/esm/web3/OdisPayments.js", - "require": "./dist/cjs/web3/OdisPayments.js", - "types": "./dist/types/web3/OdisPayments.d.ts" - }, - "./web3/Proxy": { - "import": "./dist/esm/web3/Proxy.js", - "require": "./dist/cjs/web3/Proxy.js", - "types": "./dist/types/web3/Proxy.d.ts" - }, - "./web3/Random": { - "import": "./dist/esm/web3/Random.js", - "require": "./dist/cjs/web3/Random.js", - "types": "./dist/types/web3/Random.d.ts" - }, - "./web3/Registry": { - "import": "./dist/esm/web3/Registry.js", - "require": "./dist/cjs/web3/Registry.js", - "types": "./dist/types/web3/Registry.d.ts" - }, - "./web3/ReleaseGold": { - "import": "./dist/esm/web3/ReleaseGold.js", - "require": "./dist/cjs/web3/ReleaseGold.js", - "types": "./dist/types/web3/ReleaseGold.d.ts" - }, - "./web3/SortedOracles": { - "import": "./dist/esm/web3/SortedOracles.js", - "require": "./dist/cjs/web3/SortedOracles.js", - "types": "./dist/types/web3/SortedOracles.d.ts" - }, - "./web3/UniswapFeeHandlerSeller": { - "import": "./dist/esm/web3/UniswapFeeHandlerSeller.js", - "require": "./dist/cjs/web3/UniswapFeeHandlerSeller.js", - "types": "./dist/types/web3/UniswapFeeHandlerSeller.d.ts" - }, - "./web3/Validators": { - "import": "./dist/esm/web3/Validators.js", - "require": "./dist/cjs/web3/Validators.js", - "types": "./dist/types/web3/Validators.d.ts" - }, - "./web3/mento/Exchange": { - "import": "./dist/esm/web3/mento/Exchange.js", - "require": "./dist/cjs/web3/mento/Exchange.js", - "types": "./dist/types/web3/mento/Exchange.d.ts" - }, - "./web3/mento/ExchangeBRL": { - "import": "./dist/esm/web3/mento/ExchangeBRL.js", - "require": "./dist/cjs/web3/mento/ExchangeBRL.js", - "types": "./dist/types/web3/mento/ExchangeBRL.d.ts" - }, - "./web3/mento/ExchangeEUR": { - "import": "./dist/esm/web3/mento/ExchangeEUR.js", - "require": "./dist/cjs/web3/mento/ExchangeEUR.js", - "types": "./dist/types/web3/mento/ExchangeEUR.d.ts" - }, - "./web3/mento/GrandaMento": { - "import": "./dist/esm/web3/mento/GrandaMento.js", - "require": "./dist/cjs/web3/mento/GrandaMento.js", - "types": "./dist/types/web3/mento/GrandaMento.d.ts" - }, - "./web3/mento/Reserve": { - "import": "./dist/esm/web3/mento/Reserve.js", - "require": "./dist/cjs/web3/mento/Reserve.js", - "types": "./dist/types/web3/mento/Reserve.d.ts" - }, - "./web3/mento/ReserveSpenderMultiSig": { - "import": "./dist/esm/web3/mento/ReserveSpenderMultiSig.js", - "require": "./dist/cjs/web3/mento/ReserveSpenderMultiSig.js", - "types": "./dist/types/web3/mento/ReserveSpenderMultiSig.d.ts" - }, - "./web3/mento/StableToken": { - "import": "./dist/esm/web3/mento/StableToken.js", - "require": "./dist/cjs/web3/mento/StableToken.js", - "types": "./dist/types/web3/mento/StableToken.d.ts" - }, - "./web3/mento/StableTokenBRL": { - "import": "./dist/esm/web3/mento/StableTokenBRL.js", - "require": "./dist/cjs/web3/mento/StableTokenBRL.js", - "types": "./dist/types/web3/mento/StableTokenBRL.d.ts" - }, - "./web3/mento/StableTokenEUR": { - "import": "./dist/esm/web3/mento/StableTokenEUR.js", - "require": "./dist/cjs/web3/mento/StableTokenEUR.js", - "types": "./dist/types/web3/mento/StableTokenEUR.d.ts" - } - } -} \ No newline at end of file diff --git a/packages/protocol/abis/tsconfig-cjs.json b/packages/protocol/abis/tsconfig-cjs.json deleted file mode 100644 index 50bbdbe9f..000000000 --- a/packages/protocol/abis/tsconfig-cjs.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "esModuleInterop": false, - "declaration": false, - "module": "CommonJS", - "outDir": "./dist/cjs" - }, -} \ No newline at end of file diff --git a/packages/protocol/abis/tsconfig-esm.json b/packages/protocol/abis/tsconfig-esm.json deleted file mode 100644 index 36251a4ed..000000000 --- a/packages/protocol/abis/tsconfig-esm.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "target": "ES2020", - "declaration": false, - "module": "ES2020", - "outDir": "./dist/esm" - }, -} \ No newline at end of file diff --git a/packages/protocol/abis/tsconfig-types.json b/packages/protocol/abis/tsconfig-types.json deleted file mode 100644 index caf132b8e..000000000 --- a/packages/protocol/abis/tsconfig-types.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "./dist/types", - "declaration": true, - "emitDeclarationOnly": true - } -} \ No newline at end of file diff --git a/packages/protocol/abis/tsconfig.json b/packages/protocol/abis/tsconfig.json deleted file mode 100644 index 0ee28e1c5..000000000 --- a/packages/protocol/abis/tsconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "compileOnSave": false, - "compilerOptions": { - "allowSyntheticDefaultImports": true, - "esModuleInterop": true, - "baseUrl": ".", - "strict": true, - "moduleResolution": "node16", - "noUnusedLocals": true, - "noUnusedParameters": true, - "removeComments": true, - "skipLibCheck": true, - "sourceMap": false, - "target": "ES5", - "downlevelIteration": true, - "resolveJsonModule": true, - "declaration": false, - "rootDir": "./src-generated", - }, - "include": ["./src-generated"], -} \ No newline at end of file diff --git a/packages/protocol/contractPackages.ts b/packages/protocol/contractPackages.ts deleted file mode 100644 index 577823d83..000000000 --- a/packages/protocol/contractPackages.ts +++ /dev/null @@ -1,54 +0,0 @@ -export interface ContractPackage { - path?: string - folderPath?: string - name: string - contracts: string[] - contractsFolder?: string - proxyContracts?: string[] - truffleConfig?: string - solidityVersion?: string - proxiesPath?: string -} - -export const MENTO_PACKAGE: ContractPackage = { - path: 'mento-core', - contractsFolder: 'contracts', - folderPath: 'lib', - name: 'mento', - contracts: [ - 'Exchange', - 'ExchangeEUR', - 'ExchangeBRL', - 'GrandaMento', - 'Reserve', - 'ReserveSpenderMultiSig', - 'StableToken', - 'StableTokenEUR', - 'StableTokenBRL', - ], - proxyContracts: [ - 'ExchangeBRLProxy', - 'ExchangeEURProxy', - 'ExchangeProxy', - 'GrandaMentoProxy', - 'ReserveProxy', - 'ReserveSpenderMultiSigProxy', - 'StableTokenBRLProxy', - 'StableTokenEURProxy', - 'StableTokenProxy', - ], - truffleConfig: 'truffle-config.js', -} - -export const SOLIDITY_08_PACKAGE: ContractPackage = { - path: 'contracts-0.8', - contractsFolder: '', - folderPath: '', - name: '0.8', - proxiesPath: '/', // Proxies are still with 0.5 contracts - // Proxies shouldn't have to be added to a list manually - // https://github.com/celo-org/celo-monorepo/issues/10555 - contracts: ['GasPriceMinimum'], - proxyContracts: ['GasPriceMinimumProxy'], - truffleConfig: 'truffle-config0.8.js', -} diff --git a/packages/protocol/contracts-0.8/common/GasPriceMinimum.sol b/packages/protocol/contracts-0.8/common/GasPriceMinimum.sol deleted file mode 100644 index f09dc6f88..000000000 --- a/packages/protocol/contracts-0.8/common/GasPriceMinimum.sol +++ /dev/null @@ -1,225 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.7 <0.8.20; - -import "@openzeppelin/contracts8/access/Ownable.sol"; - -import "../../contracts/common/CalledByVm.sol"; -import "../../contracts/common/Initializable.sol"; -import "../../contracts/common/interfaces/ICeloVersionedContract.sol"; -import "../../contracts/common/FixidityLib.sol"; -import "./UsingRegistry.sol"; -import "../../contracts/stability/interfaces/ISortedOracles.sol"; - -/** - * @title Stores and provides gas price minimum for various currencies. - */ -contract GasPriceMinimum is - ICeloVersionedContract, - Ownable, - Initializable, - UsingRegistry, - CalledByVm -{ - using FixidityLib for FixidityLib.Fraction; - - event TargetDensitySet(uint256 targetDensity); - event GasPriceMinimumFloorSet(uint256 gasPriceMinimumFloor); - event AdjustmentSpeedSet(uint256 adjustmentSpeed); - event GasPriceMinimumUpdated(uint256 gasPriceMinimum); - event BaseFeeOpCodeActivationBlockSet(uint256 baseFeeOpCodeActivationBlock); - - uint256 public deprecated_gasPriceMinimum; - uint256 public gasPriceMinimumFloor; - - // Block congestion level targeted by the gas price minimum calculation. - FixidityLib.Fraction public targetDensity; - - // Speed of gas price minimum adjustment due to congestion. - FixidityLib.Fraction public adjustmentSpeed; - - uint256 public baseFeeOpCodeActivationBlock; - - /** - * @notice Sets initialized == true on implementation contracts - * @param test Set to true to skip implementation initialization - */ - constructor(bool test) public Initializable(test) {} - - /** - * @notice Returns the storage, major, minor, and patch version of the contract. - * @return Storage version of the contract. - * @return Major version of the contract. - * @return Minor version of the contract. - * @return Patch version of the contract. - */ - function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { - return (1, 2, 0, 0); - } - - /** - * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. - * @param _registryAddress The address of the registry core smart contract. - * @param _gasPriceMinimumFloor The lowest value the gas price minimum can be. - * @param _targetDensity The target gas fullness of blocks, expressed as a fixidity fraction. - * @param _adjustmentSpeed How quickly the minimum changes, expressed as a fixidity fraction. - * @param _baseFeeOpCodeActivationBlock Block number where the baseFee opCode is activated - */ - function initialize( - address _registryAddress, - uint256 _gasPriceMinimumFloor, - uint256 _targetDensity, - uint256 _adjustmentSpeed, - uint256 _baseFeeOpCodeActivationBlock - ) external initializer { - _transferOwnership(msg.sender); - setRegistry(_registryAddress); - deprecated_gasPriceMinimum = _gasPriceMinimumFloor; - setGasPriceMinimumFloor(_gasPriceMinimumFloor); - setTargetDensity(_targetDensity); - setAdjustmentSpeed(_adjustmentSpeed); - _setBaseFeeOpCodeActivationBlock(_baseFeeOpCodeActivationBlock, true); - } - - /** - * @notice Set a multiplier that impacts how quickly gas price minimum is adjusted. - * @param _adjustmentSpeed How quickly the minimum changes, expressed as a fixidity fraction. - * @dev Value is expected to be < 1. - */ - function setAdjustmentSpeed(uint256 _adjustmentSpeed) public onlyOwner { - adjustmentSpeed = FixidityLib.wrap(_adjustmentSpeed); - require(adjustmentSpeed.lt(FixidityLib.fixed1()), "adjustment speed must be smaller than 1"); - emit AdjustmentSpeedSet(_adjustmentSpeed); - } - - /** - * @notice Set the block density targeted by the gas price minimum algorithm. - * @param _targetDensity The target gas fullness of blocks, expressed as a fixidity fraction. - * @dev Value is expected to be < 1. - */ - function setTargetDensity(uint256 _targetDensity) public onlyOwner { - targetDensity = FixidityLib.wrap(_targetDensity); - require(targetDensity.lt(FixidityLib.fixed1()), "target density must be smaller than 1"); - emit TargetDensitySet(_targetDensity); - } - - /** - * @notice Set the minimum gas price treshold. - * @param _gasPriceMinimumFloor The lowest value the gas price minimum can be. - * @dev Value is expected to be > 0. - */ - function setGasPriceMinimumFloor(uint256 _gasPriceMinimumFloor) public onlyOwner { - require(_gasPriceMinimumFloor > 0, "gas price minimum floor must be greater than zero"); - gasPriceMinimumFloor = _gasPriceMinimumFloor; - emit GasPriceMinimumFloorSet(_gasPriceMinimumFloor); - } - - /** - * @notice Set the activation block of the baseFee opCode. - * @param _baseFeeOpCodeActivationBlock Block number where the baseFee opCode is activated - * @dev Value is expected to be > 0. - */ - function setBaseFeeOpCodeActivationBlock(uint256 _baseFeeOpCodeActivationBlock) - external - onlyOwner - { - _setBaseFeeOpCodeActivationBlock(_baseFeeOpCodeActivationBlock, false); - } - - /** - * @notice Set the activation block of the baseFee opCode. - * @param _baseFeeOpCodeActivationBlock Block number where the baseFee opCode is activated - * @dev Value is expected to be > 0. - */ - function _setBaseFeeOpCodeActivationBlock(uint256 _baseFeeOpCodeActivationBlock, bool allowZero) - private - onlyOwner - { - require( - allowZero || _baseFeeOpCodeActivationBlock > 0, - "baseFee opCode activation block must be greater than zero" - ); - baseFeeOpCodeActivationBlock = _baseFeeOpCodeActivationBlock; - emit BaseFeeOpCodeActivationBlockSet(_baseFeeOpCodeActivationBlock); - } - - function gasPriceMinimum() public view returns (uint256) { - if (baseFeeOpCodeActivationBlock > 0 && block.number >= baseFeeOpCodeActivationBlock) { - return block.basefee; - } else { - return deprecated_gasPriceMinimum; - } - } - - /** - * @notice Retrieve the current gas price minimum for a currency. - * @param tokenAddress The currency the gas price should be in (defaults to gold). - * @return current gas price minimum in the requested currency - */ - function getGasPriceMinimum(address tokenAddress) external view returns (uint256) { - if ( - tokenAddress == address(0) || - tokenAddress == registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID) - ) { - return gasPriceMinimum(); - } else { - ISortedOracles sortedOracles = ISortedOracles( - registry.getAddressForOrDie(SORTED_ORACLES_REGISTRY_ID) - ); - uint256 rateNumerator; - uint256 rateDenominator; - (rateNumerator, rateDenominator) = sortedOracles.medianRate(tokenAddress); - return ((gasPriceMinimum() * rateNumerator) / rateDenominator); - } - } - - /** - * @notice Adjust the gas price minimum based on governable parameters - * and block congestion. - * @param blockGasTotal The amount of gas in the most recent block. - * @param blockGasLimit The maxBlockGasLimit of the past block. - * @return result of the calculation (new gas price minimum) - */ - function updateGasPriceMinimum(uint256 blockGasTotal, uint256 blockGasLimit) - external - onlyVm - returns (uint256) - { - deprecated_gasPriceMinimum = getUpdatedGasPriceMinimum(blockGasTotal, blockGasLimit); - emit GasPriceMinimumUpdated(deprecated_gasPriceMinimum); - return deprecated_gasPriceMinimum; - } - - /** - * @notice Calculates the gas price minimum based on governable parameters - * and block congestion. - * @param blockGasTotal The amount of gas in the most recent block. - * @param blockGasLimit The maxBlockGasLimit of the past block. - * @return result of the calculation (new gas price minimum) - * @dev Calculate using the following formula: - * oldGasPriceMinimum * (1 + (adjustmentSpeed * (blockDensity - targetDensity))) + 1. - */ - function getUpdatedGasPriceMinimum(uint256 blockGasTotal, uint256 blockGasLimit) - public - view - returns (uint256) - { - FixidityLib.Fraction memory blockDensity = FixidityLib.newFixedFraction( - blockGasTotal, - blockGasLimit - ); - bool densityGreaterThanTarget = blockDensity.gt(targetDensity); - FixidityLib.Fraction memory densityDelta = densityGreaterThanTarget - ? blockDensity.subtract(targetDensity) - : targetDensity.subtract(blockDensity); - FixidityLib.Fraction memory adjustment = densityGreaterThanTarget - ? FixidityLib.fixed1().add(adjustmentSpeed.multiply(densityDelta)) - : FixidityLib.fixed1().subtract(adjustmentSpeed.multiply(densityDelta)); - - uint256 newGasPriceMinimum = adjustment - .multiply(FixidityLib.newFixed(gasPriceMinimum())) - .add(FixidityLib.fixed1()) - .fromFixed(); - - return newGasPriceMinimum >= gasPriceMinimumFloor ? newGasPriceMinimum : gasPriceMinimumFloor; - } -} diff --git a/packages/protocol/contracts-0.8/common/UsingRegistry.sol b/packages/protocol/contracts-0.8/common/UsingRegistry.sol deleted file mode 100644 index 9599f0678..000000000 --- a/packages/protocol/contracts-0.8/common/UsingRegistry.sol +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.8.0 <0.8.20; - -// Note: This is not an exact copy of UsingRegistry or UsingRegistryV2 in the contract's folder -// because Mento's interfaces still don't support Solidity 0.8 - -import "@openzeppelin/contracts8/access/Ownable.sol"; -import "@openzeppelin/contracts8/token/ERC20/IERC20.sol"; - -import "../../contracts/common/interfaces/IRegistry.sol"; - -contract UsingRegistry is Ownable { - event RegistrySet(address indexed registryAddress); - - // solhint-disable state-visibility - bytes32 constant ACCOUNTS_REGISTRY_ID = keccak256(abi.encodePacked("Accounts")); - bytes32 constant ATTESTATIONS_REGISTRY_ID = keccak256(abi.encodePacked("Attestations")); - bytes32 constant DOWNTIME_SLASHER_REGISTRY_ID = keccak256(abi.encodePacked("DowntimeSlasher")); - bytes32 constant DOUBLE_SIGNING_SLASHER_REGISTRY_ID = keccak256( - abi.encodePacked("DoubleSigningSlasher") - ); - bytes32 constant ELECTION_REGISTRY_ID = keccak256(abi.encodePacked("Election")); - bytes32 constant EXCHANGE_REGISTRY_ID = keccak256(abi.encodePacked("Exchange")); - bytes32 constant FEE_CURRENCY_WHITELIST_REGISTRY_ID = keccak256( - abi.encodePacked("FeeCurrencyWhitelist") - ); - bytes32 constant FREEZER_REGISTRY_ID = keccak256(abi.encodePacked("Freezer")); - bytes32 constant GOLD_TOKEN_REGISTRY_ID = keccak256(abi.encodePacked("GoldToken")); - bytes32 constant GOVERNANCE_REGISTRY_ID = keccak256(abi.encodePacked("Governance")); - bytes32 constant GOVERNANCE_SLASHER_REGISTRY_ID = keccak256( - abi.encodePacked("GovernanceSlasher") - ); - bytes32 constant LOCKED_GOLD_REGISTRY_ID = keccak256(abi.encodePacked("LockedGold")); - bytes32 constant RESERVE_REGISTRY_ID = keccak256(abi.encodePacked("Reserve")); - bytes32 constant RANDOM_REGISTRY_ID = keccak256(abi.encodePacked("Random")); - bytes32 constant SORTED_ORACLES_REGISTRY_ID = keccak256(abi.encodePacked("SortedOracles")); - bytes32 constant STABLE_TOKEN_REGISTRY_ID = keccak256(abi.encodePacked("StableToken")); - bytes32 constant VALIDATORS_REGISTRY_ID = keccak256(abi.encodePacked("Validators")); - // solhint-enable state-visibility - - IRegistry public registry; - - modifier onlyRegisteredContract(bytes32 identifierHash) { - require(registry.getAddressForOrDie(identifierHash) == msg.sender, "only registered contract"); - _; - } - - modifier onlyRegisteredContracts(bytes32[] memory identifierHashes) { - require(registry.isOneOf(identifierHashes, msg.sender), "only registered contracts"); - _; - } - - /** - * @notice Updates the address pointing to a Registry contract. - * @param registryAddress The address of a registry contract for routing to other contracts. - */ - function setRegistry(address registryAddress) public onlyOwner { - require(registryAddress != address(0), "Cannot register the null address"); - registry = IRegistry(registryAddress); - emit RegistrySet(registryAddress); - } - - function getGoldToken() internal view returns (IERC20) { - return IERC20(registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID)); - } -} diff --git a/packages/protocol/contracts/.npmignore b/packages/protocol/contracts/.npmignore deleted file mode 100644 index ea6a770f1..000000000 --- a/packages/protocol/contracts/.npmignore +++ /dev/null @@ -1,4 +0,0 @@ -**/test/** -uniswap/** -package.abis.json -README.abis.md diff --git a/packages/protocol/contracts/Migrations.sol b/packages/protocol/contracts/Migrations.sol deleted file mode 100644 index d1008cca7..000000000 --- a/packages/protocol/contracts/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.13; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/contracts/README.md b/packages/protocol/contracts/README.md deleted file mode 100644 index ddd467565..000000000 --- a/packages/protocol/contracts/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# Celo core contracts - -Smart contracts for the Celo protocol. - -## Usage - -### Installation - -```bash -npm install @celo/contracts -``` - -or - -```bash -yarn add @celo/contracts -``` - -### In your Solidity contracts - -```solidity -pragma solidity ^0.5.13; - -import '@celo/contracts/common/UsingRegistryV2.sol'; - -contract Example is UsingRegistryV2 { - constructor() public { - require(getAccounts().createAccount()); - } -} - -``` - -## License - -The contents of this package are licensed under the terms of the GNU Lesser Public License V3 diff --git a/packages/protocol/contracts/common/Accounts.sol b/packages/protocol/contracts/common/Accounts.sol deleted file mode 100644 index ac9372096..000000000 --- a/packages/protocol/contracts/common/Accounts.sol +++ /dev/null @@ -1,1133 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./interfaces/IAccounts.sol"; - -import "../common/FixidityLib.sol"; -import "../common/Initializable.sol"; -import "../common/interfaces/ICeloVersionedContract.sol"; -import "../common/Signatures.sol"; -import "../common/UsingRegistry.sol"; -import "../common/libraries/ReentrancyGuard.sol"; - -contract Accounts is - IAccounts, - ICeloVersionedContract, - Ownable, - ReentrancyGuard, - Initializable, - UsingRegistry -{ - using FixidityLib for FixidityLib.Fraction; - using SafeMath for uint256; - - struct Signers { - // The address that is authorized to vote in governance and validator elections on behalf of the - // account. The account can vote as well, whether or not a vote signing key has been specified. - address vote; - // The address that is authorized to manage a validator or validator group and sign consensus - // messages on behalf of the account. The account can manage the validator, whether or not a - // validator signing key has been specified. However, if a validator signing key has been - // specified, only that key may actually participate in consensus. - address validator; - // The address of the key with which this account wants to sign attestations on the Attestations - // contract - address attestation; - } - - struct SignerAuthorization { - bool started; - bool completed; - } - - struct Account { - bool exists; - // [Deprecated] Each account may authorize signing keys to use for voting, - // validating or attestation. These keys may not be keys of other accounts, - // and may not be authorized by any other account for any purpose. - Signers signers; - // The address at which the account expects to receive transfers. If it's empty/0x0, the - // account indicates that an address exchange should be initiated with the dataEncryptionKey - address walletAddress; - // An optional human readable identifier for the account - string name; - // The ECDSA public key used to encrypt and decrypt data for this account - bytes dataEncryptionKey; - // The URL under which an account adds metadata and claims - string metadataURL; - } - - struct PaymentDelegation { - // Address that should receive a fraction of validator payments. - address beneficiary; - // Fraction of payment to delegate to `beneficiary`. - FixidityLib.Fraction fraction; - } - - mapping(address => Account) internal accounts; - // Maps authorized signers to the account that provided the authorization. - mapping(address => address) public authorizedBy; - // Default signers by account (replaces the legacy Signers struct on Account) - mapping(address => mapping(bytes32 => address)) defaultSigners; - // All signers and their roles for a given account - // solhint-disable-next-line max-line-length - mapping(address => mapping(bytes32 => mapping(address => SignerAuthorization))) signerAuthorizations; - - bytes32 public constant EIP712_AUTHORIZE_SIGNER_TYPEHASH = keccak256( - "AuthorizeSigner(address account,address signer,bytes32 role)" - ); - bytes32 public eip712DomainSeparator; - - // A per-account list of CIP8 storage roots, bypassing CIP3. - mapping(address => bytes[]) public offchainStorageRoots; - - // Optional per-account validator payment delegation information. - mapping(address => PaymentDelegation) internal paymentDelegations; - - bytes32 constant ValidatorSigner = keccak256(abi.encodePacked("celo.org/core/validator")); - bytes32 constant AttestationSigner = keccak256(abi.encodePacked("celo.org/core/attestation")); - bytes32 constant VoteSigner = keccak256(abi.encodePacked("celo.org/core/vote")); - - event AttestationSignerAuthorized(address indexed account, address signer); - event VoteSignerAuthorized(address indexed account, address signer); - event ValidatorSignerAuthorized(address indexed account, address signer); - event SignerAuthorized(address indexed account, address signer, bytes32 indexed role); - event SignerAuthorizationStarted(address indexed account, address signer, bytes32 indexed role); - event SignerAuthorizationCompleted(address indexed account, address signer, bytes32 indexed role); - event AttestationSignerRemoved(address indexed account, address oldSigner); - event VoteSignerRemoved(address indexed account, address oldSigner); - event ValidatorSignerRemoved(address indexed account, address oldSigner); - event IndexedSignerSet(address indexed account, address signer, bytes32 role); - event IndexedSignerRemoved(address indexed account, address oldSigner, bytes32 role); - event DefaultSignerSet(address indexed account, address signer, bytes32 role); - event DefaultSignerRemoved(address indexed account, address oldSigner, bytes32 role); - event LegacySignerSet(address indexed account, address signer, bytes32 role); - event LegacySignerRemoved(address indexed account, address oldSigner, bytes32 role); - event SignerRemoved(address indexed account, address oldSigner, bytes32 indexed role); - event AccountDataEncryptionKeySet(address indexed account, bytes dataEncryptionKey); - event AccountNameSet(address indexed account, string name); - event AccountMetadataURLSet(address indexed account, string metadataURL); - event AccountWalletAddressSet(address indexed account, address walletAddress); - event AccountCreated(address indexed account); - event OffchainStorageRootAdded(address indexed account, bytes url); - event OffchainStorageRootRemoved(address indexed account, bytes url, uint256 index); - event PaymentDelegationSet(address indexed beneficiary, uint256 fraction); - - /** - * @notice Sets initialized == true on implementation contracts - * @param test Set to true to skip implementation initialization - */ - constructor(bool test) public Initializable(test) {} - - /** - * @notice Returns the storage, major, minor, and patch version of the contract. - * @return Storage version of the contract. - * @return Major version of the contract. - * @return Minor version of the contract. - * @return Patch version of the contract. - */ - function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { - return (1, 1, 4, 1); - } - - /** - * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. - * @param registryAddress The address of the registry core smart contract. - */ - function initialize(address registryAddress) external initializer { - _transferOwnership(msg.sender); - setRegistry(registryAddress); - setEip712DomainSeparator(); - } - - /** - * @notice Sets the EIP712 domain separator for the Celo Accounts abstraction. - */ - function setEip712DomainSeparator() public { - uint256 chainId; - assembly { - chainId := chainid - } - - eip712DomainSeparator = keccak256( - abi.encode( - keccak256( - "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" - ), - keccak256(bytes("Celo Core Contracts")), - keccak256("1.0"), - chainId, - address(this) - ) - ); - } - - /** - * @notice Convenience Setter for the dataEncryptionKey and wallet address for an account - * @param name A string to set as the name of the account - * @param dataEncryptionKey secp256k1 public key for data encryption. Preferably compressed. - * @param walletAddress The wallet address to set for the account - * @param v The recovery id of the incoming ECDSA signature. - * @param r Output value r of the ECDSA signature. - * @param s Output value s of the ECDSA signature. - * @dev v, r, s constitute `signer`'s signature on `msg.sender` (unless the wallet address - * is 0x0 or msg.sender). - */ - function setAccount( - string calldata name, - bytes calldata dataEncryptionKey, - address walletAddress, - uint8 v, - bytes32 r, - bytes32 s - ) external { - if (!isAccount(msg.sender)) { - createAccount(); - } - setName(name); - setAccountDataEncryptionKey(dataEncryptionKey); - setWalletAddress(walletAddress, v, r, s); - } - - /** - * @notice Creates an account. - * @return True if account creation succeeded. - */ - function createAccount() public returns (bool) { - require( - isNotAccount(msg.sender) && isNotAuthorizedSigner(msg.sender), - "Account already exists or address is an authorized signer for another account" - ); - Account storage account = accounts[msg.sender]; - account.exists = true; - emit AccountCreated(msg.sender); - return true; - } - - /** - * @notice Setter for the name of an account. - * @param name The name to set. - */ - function setName(string memory name) public { - require(isAccount(msg.sender), "Register with createAccount to set account name"); - Account storage account = accounts[msg.sender]; - account.name = name; - emit AccountNameSet(msg.sender, name); - } - - /** - * @notice Setter for the wallet address for an account - * @param walletAddress The wallet address to set for the account - * @param v The recovery id of the incoming ECDSA signature. - * @param r Output value r of the ECDSA signature. - * @param s Output value s of the ECDSA signature. - * @dev Wallet address can be zero. This means that the owner of the wallet - * does not want to be paid directly without interaction, and instead wants users to - * contact them, using the data encryption key, and arrange a payment. - * @dev v, r, s constitute `signer`'s signature on `msg.sender` (unless the wallet address - * is 0x0 or msg.sender). - */ - function setWalletAddress(address walletAddress, uint8 v, bytes32 r, bytes32 s) public { - require(isAccount(msg.sender), "Unknown account"); - if (!(walletAddress == msg.sender || walletAddress == address(0x0))) { - address signer = Signatures.getSignerOfAddress(msg.sender, v, r, s); - require(signer == walletAddress, "Invalid signature"); - } - Account storage account = accounts[msg.sender]; - account.walletAddress = walletAddress; - emit AccountWalletAddressSet(msg.sender, walletAddress); - } - - /** - * @notice Setter for the data encryption key and version. - * @param dataEncryptionKey secp256k1 public key for data encryption. Preferably compressed. - */ - function setAccountDataEncryptionKey(bytes memory dataEncryptionKey) public { - require(dataEncryptionKey.length >= 33, "data encryption key length <= 32"); - Account storage account = accounts[msg.sender]; - account.dataEncryptionKey = dataEncryptionKey; - emit AccountDataEncryptionKeySet(msg.sender, dataEncryptionKey); - } - - /** - * @notice Setter for the metadata of an account. - * @param metadataURL The URL to access the metadata. - */ - function setMetadataURL(string calldata metadataURL) external { - require(isAccount(msg.sender), "Unknown account"); - Account storage account = accounts[msg.sender]; - account.metadataURL = metadataURL; - emit AccountMetadataURLSet(msg.sender, metadataURL); - } - - /** - * @notice Adds a new CIP8 storage root. - * @param url The URL pointing to the offchain storage root. - */ - function addStorageRoot(bytes calldata url) external { - require(isAccount(msg.sender), "Unknown account"); - offchainStorageRoots[msg.sender].push(url); - emit OffchainStorageRootAdded(msg.sender, url); - } - - /** - * @notice Removes a CIP8 storage root. - * @param index The index of the storage root to be removed in the account's - * list of storage roots. - * @dev The order of storage roots may change after this operation (the last - * storage root will be moved to `index`), be aware of this if removing - * multiple storage roots at a time. - */ - function removeStorageRoot(uint256 index) external { - require(isAccount(msg.sender), "Unknown account"); - require(index < offchainStorageRoots[msg.sender].length, "Invalid storage root index"); - uint256 lastIndex = offchainStorageRoots[msg.sender].length - 1; - bytes memory url = offchainStorageRoots[msg.sender][index]; - offchainStorageRoots[msg.sender][index] = offchainStorageRoots[msg.sender][lastIndex]; - offchainStorageRoots[msg.sender].length--; - emit OffchainStorageRootRemoved(msg.sender, url, index); - } - - /** - * @notice Returns the full list of offchain storage roots for an account. - * @param account The account whose storage roots to return. - * @return Concatenated storage root URLs. - * @return Lengths of storage root URLs. - */ - function getOffchainStorageRoots(address account) - external - view - returns (bytes memory, uint256[] memory) - { - require(isAccount(account), "Unknown account"); - uint256 numberRoots = offchainStorageRoots[account].length; - uint256 totalLength = 0; - for (uint256 i = 0; i < numberRoots; i++) { - totalLength = totalLength.add(offchainStorageRoots[account][i].length); - } - - bytes memory concatenated = new bytes(totalLength); - uint256 lastIndex = 0; - uint256[] memory lengths = new uint256[](numberRoots); - for (uint256 i = 0; i < numberRoots; i++) { - bytes storage root = offchainStorageRoots[account][i]; - lengths[i] = root.length; - for (uint256 j = 0; j < lengths[i]; j++) { - concatenated[lastIndex] = root[j]; - lastIndex++; - } - } - - return (concatenated, lengths); - } - - /** - * @notice Sets validator payment delegation settings. - * @param beneficiary The address that should receive a portion of validator - * payments. - * @param fraction The fraction of the validator's payment that should be - * diverted to `beneficiary` every epoch, given as FixidityLib value. Must not - * be greater than 1. - * @dev Use `deletePaymentDelegation` to unset the payment delegation. - */ - function setPaymentDelegation(address beneficiary, uint256 fraction) public { - require(isAccount(msg.sender), "Must first register address with Account.createAccount"); - require(beneficiary != address(0), "Beneficiary cannot be address 0x0"); - FixidityLib.Fraction memory f = FixidityLib.wrap(fraction); - require(f.lte(FixidityLib.fixed1()), "Fraction must not be greater than 1"); - paymentDelegations[msg.sender] = PaymentDelegation(beneficiary, f); - emit PaymentDelegationSet(beneficiary, fraction); - } - - /** - * @notice Removes a validator's payment delegation by setting benficiary and - * fraction to 0. - */ - function deletePaymentDelegation() public { - require(isAccount(msg.sender), "Must first register address with Account.createAccount"); - paymentDelegations[msg.sender] = PaymentDelegation(address(0x0), FixidityLib.wrap(0)); - emit PaymentDelegationSet(address(0x0), 0); - } - - /** - * @notice Gets validator payment delegation settings. - * @param account Account of the validator. - * @return Beneficiary address of payment delegated. - * @return Fraction of payment delegated. - */ - function getPaymentDelegation(address account) external view returns (address, uint256) { - PaymentDelegation storage delegation = paymentDelegations[account]; - return (delegation.beneficiary, delegation.fraction.unwrap()); - } - - /** - * @notice Set the indexed signer for a specific role - * @param signer the address to set as default - * @param role the role to register a default signer for - */ - function setIndexedSigner(address signer, bytes32 role) public { - require(isAccount(msg.sender), "Must first register address with Account.createAccount"); - require(isNotAccount(signer), "Cannot authorize account as signer"); - require( - isNotAuthorizedSignerForAnotherAccount(msg.sender, signer), - "Not a signer for this account" - ); - require(isSigner(msg.sender, signer, role), "Must authorize signer before setting as default"); - - Account storage account = accounts[msg.sender]; - if (isLegacyRole(role)) { - if (role == VoteSigner) { - account.signers.vote = signer; - } else if (role == AttestationSigner) { - account.signers.attestation = signer; - } else if (role == ValidatorSigner) { - account.signers.validator = signer; - } - emit LegacySignerSet(msg.sender, signer, role); - } else { - defaultSigners[msg.sender][role] = signer; - emit DefaultSignerSet(msg.sender, signer, role); - } - - emit IndexedSignerSet(msg.sender, signer, role); - } - - /** - * @notice Authorizes an address to act as a signer, for `role`, on behalf of the account. - * @param signer The address of the signing key to authorize. - * @param role The role to authorize signing for. - * @param v The recovery id of the incoming ECDSA signature. - * @param r Output value r of the ECDSA signature. - * @param s Output value s of the ECDSA signature. - * @dev v, r, s constitute `signer`'s EIP712 signature over `role`, `msg.sender` - * and `signer`. - */ - function authorizeSignerWithSignature(address signer, bytes32 role, uint8 v, bytes32 r, bytes32 s) - public - { - authorizeAddressWithRole(signer, role, v, r, s); - signerAuthorizations[msg.sender][role][signer] = SignerAuthorization({ - started: true, - completed: true - }); - - emit SignerAuthorized(msg.sender, signer, role); - } - - function legacyAuthorizeSignerWithSignature( - address signer, - bytes32 role, - uint8 v, - bytes32 r, - bytes32 s - ) private { - authorizeAddress(signer, v, r, s); - signerAuthorizations[msg.sender][role][signer] = SignerAuthorization({ - started: true, - completed: true - }); - - emit SignerAuthorized(msg.sender, signer, role); - } - - /** - * @notice Authorizes an address to sign votes on behalf of the account. - * @param signer The address of the signing key to authorize. - * @param v The recovery id of the incoming ECDSA signature. - * @param r Output value r of the ECDSA signature. - * @param s Output value s of the ECDSA signature. - * @dev v, r, s constitute `signer`'s signature on `msg.sender`. - */ - function authorizeVoteSigner(address signer, uint8 v, bytes32 r, bytes32 s) - external - nonReentrant - { - legacyAuthorizeSignerWithSignature(signer, VoteSigner, v, r, s); - setIndexedSigner(signer, VoteSigner); - - emit VoteSignerAuthorized(msg.sender, signer); - } - - /** - * @notice Authorizes an address to sign consensus messages on behalf of the account. - * @param signer The address of the signing key to authorize. - * @param v The recovery id of the incoming ECDSA signature. - * @param r Output value r of the ECDSA signature. - * @param s Output value s of the ECDSA signature. - * @dev v, r, s constitute `signer`'s signature on `msg.sender`. - */ - function authorizeValidatorSigner(address signer, uint8 v, bytes32 r, bytes32 s) - external - nonReentrant - { - legacyAuthorizeSignerWithSignature(signer, ValidatorSigner, v, r, s); - setIndexedSigner(signer, ValidatorSigner); - - require(!getValidators().isValidator(msg.sender), "Cannot authorize validator signer"); - emit ValidatorSignerAuthorized(msg.sender, signer); - } - - /** - * @notice Authorizes an address to sign consensus messages on behalf of the account. - * @param signer The address of the signing key to authorize. - * @param v The recovery id of the incoming ECDSA signature. - * @param r Output value r of the ECDSA signature. - * @param s Output value s of the ECDSA signature. - * @param ecdsaPublicKey The ECDSA public key corresponding to `signer`. - * @dev v, r, s constitute `signer`'s signature on `msg.sender`. - */ - function authorizeValidatorSignerWithPublicKey( - address signer, - uint8 v, - bytes32 r, - bytes32 s, - bytes calldata ecdsaPublicKey - ) external nonReentrant { - legacyAuthorizeSignerWithSignature(signer, ValidatorSigner, v, r, s); - setIndexedSigner(signer, ValidatorSigner); - - require( - getValidators().updateEcdsaPublicKey(msg.sender, signer, ecdsaPublicKey), - "Failed to update ECDSA public key" - ); - emit ValidatorSignerAuthorized(msg.sender, signer); - } - - /** - * @notice Authorizes an address to sign consensus messages on behalf of the account. - * @param signer The address of the signing key to authorize. - * @param ecdsaPublicKey The ECDSA public key corresponding to `signer`. - * @param blsPublicKey The BLS public key that the validator is using for consensus, should pass - * proof of possession. 96 bytes. - * @param blsPop The BLS public key proof-of-possession, which consists of a signature on the - * account address. 48 bytes. - * @param v The recovery id of the incoming ECDSA signature. - * @param r Output value r of the ECDSA signature. - * @param s Output value s of the ECDSA signature. - * @dev v, r, s constitute `signer`'s signature on `msg.sender`. - */ - function authorizeValidatorSignerWithKeys( - address signer, - uint8 v, - bytes32 r, - bytes32 s, - bytes calldata ecdsaPublicKey, - bytes calldata blsPublicKey, - bytes calldata blsPop - ) external nonReentrant { - legacyAuthorizeSignerWithSignature(signer, ValidatorSigner, v, r, s); - setIndexedSigner(signer, ValidatorSigner); - - require( - getValidators().updatePublicKeys(msg.sender, signer, ecdsaPublicKey, blsPublicKey, blsPop), - "Failed to update validator keys" - ); - emit ValidatorSignerAuthorized(msg.sender, signer); - } - - /** - * @notice Authorizes an address to sign attestations on behalf of the account. - * @param signer The address of the signing key to authorize. - * @param v The recovery id of the incoming ECDSA signature. - * @param r Output value r of the ECDSA signature. - * @param s Output value s of the ECDSA signature. - * @dev v, r, s constitute `signer`'s signature on `msg.sender`. - */ - function authorizeAttestationSigner(address signer, uint8 v, bytes32 r, bytes32 s) public { - legacyAuthorizeSignerWithSignature(signer, AttestationSigner, v, r, s); - setIndexedSigner(signer, AttestationSigner); - - emit AttestationSignerAuthorized(msg.sender, signer); - } - - /** - * @notice Begin the process of authorizing an address to sign on behalf of the account - * @param signer The address of the signing key to authorize. - * @param role The role to authorize signing for. - */ - function authorizeSigner(address signer, bytes32 role) public { - require(isAccount(msg.sender), "Must first register sender with Account.createAccount"); - require( - isNotAccount(signer) && isNotAuthorizedSignerForAnotherAccount(msg.sender, signer), - "Cannot re-authorize address signer" - ); - - signerAuthorizations[msg.sender][role][signer] = SignerAuthorization({ - started: true, - completed: false - }); - emit SignerAuthorizationStarted(msg.sender, signer, role); - } - - /** - * @notice Finish the process of authorizing an address to sign on behalf of the account. - * @param account The address of account that authorized signing. - * @param role The role to finish authorizing for. - */ - function completeSignerAuthorization(address account, bytes32 role) public { - require( - isAccount(account), - "Unknown Account: Address that authorized signing must be a registered Account" - ); - require( - isNotAccount(msg.sender) && isNotAuthorizedSignerForAnotherAccount(account, msg.sender), - "Cannot re-authorize address signer" - ); - require( - signerAuthorizations[account][role][msg.sender].started == true, - "Signer authorization not started" - ); - - authorizedBy[msg.sender] = account; - signerAuthorizations[account][role][msg.sender].completed = true; - emit SignerAuthorizationCompleted(account, msg.sender, role); - } - - /** - * @notice Whether or not the signer has been registered as the legacy signer for role - * @param _account The address of account that authorized signing. - * @param signer The address of the signer. - * @param role The role that has been authorized. - */ - function isLegacySigner(address _account, address signer, bytes32 role) - public - view - returns (bool) - { - Account storage account = accounts[_account]; - if (role == ValidatorSigner && account.signers.validator == signer) { - return true; - } else if (role == AttestationSigner && account.signers.attestation == signer) { - return true; - } else if (role == VoteSigner && account.signers.vote == signer) { - return true; - } else { - return false; - } - } - - /** - * @notice Whether or not the signer has been registered as the default signer for role - * @param account The address of account that authorized signing. - * @param signer The address of the signer. - * @param role The role that has been authorized. - */ - function isDefaultSigner(address account, address signer, bytes32 role) - public - view - returns (bool) - { - return defaultSigners[account][role] == signer; - } - - /** - * @notice Whether or not the signer has been registered as an indexed signer for role - * @param account The address of account that authorized signing. - * @param signer The address of the signer. - * @param role The role that has been authorized. - */ - function isIndexedSigner(address account, address signer, bytes32 role) - public - view - returns (bool) - { - return - isLegacyRole(role) - ? isLegacySigner(account, signer, role) - : isDefaultSigner(account, signer, role); - } - - /** - * @notice Whether or not the signer has been registered as a signer for role - * @param account The address of account that authorized signing. - * @param signer The address of the signer. - * @param role The role that has been authorized. - */ - function isSigner(address account, address signer, bytes32 role) public view returns (bool) { - return - isLegacySigner(account, signer, role) || - (signerAuthorizations[account][role][signer].completed && authorizedBy[signer] == account); - } - - /** - * @notice Removes the signer for a default role. - * @param role The role that has been authorized. - */ - function removeDefaultSigner(bytes32 role) public { - address signer = defaultSigners[msg.sender][role]; - defaultSigners[msg.sender][role] = address(0); - emit DefaultSignerRemoved(msg.sender, signer, role); - } - - /** - * @notice Remove one of the Validator, Attestation or - * Vote signers from an account. Should only be called from - * methods that check the role is a legacy signer. - * @param role The role that has been authorized. - */ - function removeLegacySigner(bytes32 role) private { - Account storage account = accounts[msg.sender]; - - address signer; - if (role == ValidatorSigner) { - signer = account.signers.validator; - account.signers.validator = address(0); - } else if (role == AttestationSigner) { - signer = account.signers.attestation; - account.signers.attestation = address(0); - } else if (role == VoteSigner) { - signer = account.signers.vote; - account.signers.vote = address(0); - } - emit LegacySignerRemoved(msg.sender, signer, role); - } - - /** - * @notice Removes the currently authorized and indexed signer - * for a specific role - * @param role The role of the signer. - */ - function removeIndexedSigner(bytes32 role) public { - address oldSigner = getIndexedSigner(msg.sender, role); - isLegacyRole(role) ? removeLegacySigner(role) : removeDefaultSigner(role); - - emit IndexedSignerRemoved(msg.sender, oldSigner, role); - } - - /** - * @notice Removes the currently authorized signer for a specific role and - * if the signer is indexed, remove that as well. - * @param signer The address of the signer. - * @param role The role that has been authorized. - */ - function removeSigner(address signer, bytes32 role) public { - if (isIndexedSigner(msg.sender, signer, role)) { - removeIndexedSigner(role); - } - - delete signerAuthorizations[msg.sender][role][signer]; - emit SignerRemoved(msg.sender, signer, role); - } - - /** - * @notice Removes the currently authorized vote signer for the account. - * Note that the signers cannot be reauthorized after they have been removed. - */ - function removeVoteSigner() public { - address signer = getLegacySigner(msg.sender, VoteSigner); - removeSigner(signer, VoteSigner); - emit VoteSignerRemoved(msg.sender, signer); - } - - /** - * @notice Removes the currently authorized validator signer for the account - * Note that the signers cannot be reauthorized after they have been removed. - */ - function removeValidatorSigner() public { - address signer = getLegacySigner(msg.sender, ValidatorSigner); - removeSigner(signer, ValidatorSigner); - emit ValidatorSignerRemoved(msg.sender, signer); - } - - /** - * @notice Removes the currently authorized attestation signer for the account - * Note that the signers cannot be reauthorized after they have been removed. - */ - function removeAttestationSigner() public { - address signer = getLegacySigner(msg.sender, AttestationSigner); - removeSigner(signer, AttestationSigner); - emit AttestationSignerRemoved(msg.sender, signer); - } - - function signerToAccountWithRole(address signer, bytes32 role) internal view returns (address) { - address account = authorizedBy[signer]; - if (account != address(0)) { - require(isSigner(account, signer, role), "not active authorized signer for role"); - return account; - } - - require(isAccount(signer), "Must first register address with Account.createAccount"); - return signer; - } - - /** - * @notice Returns the account associated with `signer`. - * @param signer The address of the account or currently authorized attestation signer. - * @dev Fails if the `signer` is not an account or currently authorized attestation signer. - * @return The associated account that the signer is authorized to attest for. - */ - function attestationSignerToAccount(address signer) external view returns (address) { - return signerToAccountWithRole(signer, AttestationSigner); - } - - /** - * @notice Returns the account associated with `signer`. - * @param signer The address of an account or currently authorized validator signer. - * @dev Fails if the `signer` is not an account or currently authorized validator. - * @return The associated account that signer is authorized to validate for. - */ - function validatorSignerToAccount(address signer) public view returns (address) { - return signerToAccountWithRole(signer, ValidatorSigner); - } - - /** - * @notice Returns the account associated with `signer`. - * @param signer The address of the account or currently authorized vote signer. - * @dev Fails if the `signer` is not an account or currently authorized vote signer. - * @return The associated account that signer is authorized to vote for. - */ - function voteSignerToAccount(address signer) external view returns (address) { - return signerToAccountWithRole(signer, VoteSigner); - } - - /** - * @notice Returns the account associated with `signer`. - * @param signer The address of the account or previously authorized signer. - * @dev Fails if the `signer` is not an account or previously authorized signer. - * @return The associated account. - */ - function signerToAccount(address signer) external view returns (address) { - address authorizingAccount = authorizedBy[signer]; - if (authorizingAccount != address(0)) { - return authorizingAccount; - } else { - require(isAccount(signer), "Must first register address with Account.createAccount"); - return signer; - } - } - - /** - * @notice Checks whether the role is one of Vote, Validator or Attestation - * @param role The role to check - */ - function isLegacyRole(bytes32 role) public pure returns (bool) { - return role == VoteSigner || role == ValidatorSigner || role == AttestationSigner; - } - - /** - * @notice Returns the legacy signer for the specified account and - * role. If no signer has been specified it will return the account itself. - * @param _account The address of the account. - * @param role The role of the signer. - */ - function getLegacySigner(address _account, bytes32 role) public view returns (address) { - require(isLegacyRole(role), "Role is not a legacy signer"); - - Account storage account = accounts[_account]; - address signer; - if (role == ValidatorSigner) { - signer = account.signers.validator; - } else if (role == AttestationSigner) { - signer = account.signers.attestation; - } else if (role == VoteSigner) { - signer = account.signers.vote; - } - - return signer == address(0) ? _account : signer; - } - - /** - * @notice Returns the default signer for the specified account and - * role. If no signer has been specified it will return the account itself. - * @param account The address of the account. - * @param role The role of the signer. - */ - function getDefaultSigner(address account, bytes32 role) public view returns (address) { - address defaultSigner = defaultSigners[account][role]; - return defaultSigner == address(0) ? account : defaultSigner; - } - - /** - * @notice Returns the indexed signer for the specified account and role. - * If no signer has been specified it will return the account itself. - * @param account The address of the account. - * @param role The role of the signer. - */ - function getIndexedSigner(address account, bytes32 role) public view returns (address) { - return isLegacyRole(role) ? getLegacySigner(account, role) : getDefaultSigner(account, role); - } - - /** - * @notice Returns the vote signer for the specified account. - * @param account The address of the account. - * @return The address with which the account can sign votes. - */ - function getVoteSigner(address account) public view returns (address) { - return getLegacySigner(account, VoteSigner); - } - - /** - * @notice Returns the validator signer for the specified account. - * @param account The address of the account. - * @return The address with which the account can register a validator or group. - */ - function getValidatorSigner(address account) public view returns (address) { - return getLegacySigner(account, ValidatorSigner); - } - - /** - * @notice Returns the attestation signer for the specified account. - * @param account The address of the account. - * @return The address with which the account can sign attestations. - */ - function getAttestationSigner(address account) public view returns (address) { - return getLegacySigner(account, AttestationSigner); - } - - /** - * @notice Checks whether or not the account has an indexed signer - * registered for one of the legacy roles - */ - function hasLegacySigner(address account, bytes32 role) public view returns (bool) { - return getLegacySigner(account, role) != account; - } - - /** - * @notice Checks whether or not the account has an indexed signer - * registered for a role - */ - function hasDefaultSigner(address account, bytes32 role) public view returns (bool) { - return getDefaultSigner(account, role) != account; - } - - /** - * @notice Checks whether or not the account has an indexed signer - * registered for the role - */ - function hasIndexedSigner(address account, bytes32 role) public view returns (bool) { - return isLegacyRole(role) ? hasLegacySigner(account, role) : hasDefaultSigner(account, role); - } - - /** - * @notice Checks whether or not the account has a signer - * registered for the plaintext role. - * @dev See `hasIndexedSigner` for more gas efficient call. - */ - function hasAuthorizedSigner(address account, string calldata role) external view returns (bool) { - return hasIndexedSigner(account, keccak256(abi.encodePacked(role))); - } - - /** - * @notice Returns if account has specified a dedicated vote signer. - * @param account The address of the account. - * @return Whether the account has specified a dedicated vote signer. - */ - function hasAuthorizedVoteSigner(address account) external view returns (bool) { - return hasLegacySigner(account, VoteSigner); - } - - /** - * @notice Returns if account has specified a dedicated validator signer. - * @param account The address of the account. - * @return Whether the account has specified a dedicated validator signer. - */ - function hasAuthorizedValidatorSigner(address account) external view returns (bool) { - return hasLegacySigner(account, ValidatorSigner); - } - - /** - * @notice Returns if account has specified a dedicated attestation signer. - * @param account The address of the account. - * @return Whether the account has specified a dedicated attestation signer. - */ - function hasAuthorizedAttestationSigner(address account) external view returns (bool) { - return hasLegacySigner(account, AttestationSigner); - } - - /** - * @notice Getter for the name of an account. - * @param account The address of the account to get the name for. - * @return name The name of the account. - */ - function getName(address account) external view returns (string memory) { - return accounts[account].name; - } - - /** - * @notice Getter for the metadata of an account. - * @param account The address of the account to get the metadata for. - * @return metadataURL The URL to access the metadata. - */ - function getMetadataURL(address account) external view returns (string memory) { - return accounts[account].metadataURL; - } - - /** - * @notice Getter for the metadata of multiple accounts. - * @param accountsToQuery The addresses of the accounts to get the metadata for. - * @return The length of each string in bytes. - * @return All strings concatenated. - */ - function batchGetMetadataURL(address[] calldata accountsToQuery) - external - view - returns (uint256[] memory, bytes memory) - { - uint256 totalSize = 0; - uint256[] memory sizes = new uint256[](accountsToQuery.length); - for (uint256 i = 0; i < accountsToQuery.length; i = i.add(1)) { - sizes[i] = bytes(accounts[accountsToQuery[i]].metadataURL).length; - totalSize = totalSize.add(sizes[i]); - } - - bytes memory data = new bytes(totalSize); - uint256 pointer = 0; - for (uint256 i = 0; i < accountsToQuery.length; i = i.add(1)) { - for (uint256 j = 0; j < sizes[i]; j = j.add(1)) { - data[pointer] = bytes(accounts[accountsToQuery[i]].metadataURL)[j]; - pointer = pointer.add(1); - } - } - return (sizes, data); - } - - /** - * @notice Getter for the data encryption key and version. - * @param account The address of the account to get the key for - * @return dataEncryptionKey secp256k1 public key for data encryption. Preferably compressed. - */ - function getDataEncryptionKey(address account) external view returns (bytes memory) { - return accounts[account].dataEncryptionKey; - } - - /** - * @notice Getter for the wallet address for an account - * @param account The address of the account to get the wallet address for - * @return Wallet address - */ - function getWalletAddress(address account) external view returns (address) { - return accounts[account].walletAddress; - } - - /** - * @notice Check if an account already exists. - * @param account The address of the account - * @return Returns `true` if account exists. Returns `false` otherwise. - */ - function isAccount(address account) public view returns (bool) { - return (accounts[account].exists); - } - - /** - * @notice Check if an account already exists. - * @param account The address of the account - * @return Returns `false` if account exists. Returns `true` otherwise. - */ - function isNotAccount(address account) internal view returns (bool) { - return (!accounts[account].exists); - } - - /** - * @notice Check if an address has been an authorized signer for an account. - * @param signer The possibly authorized address. - * @return Returns `true` if authorized. Returns `false` otherwise. - */ - function isAuthorizedSigner(address signer) external view returns (bool) { - return (authorizedBy[signer] != address(0)); - } - - /** - * @notice Check if an address has not been an authorized signer for an account. - * @param signer The possibly authorized address. - * @return Returns `false` if authorized. Returns `true` otherwise. - */ - function isNotAuthorizedSigner(address signer) internal view returns (bool) { - return (authorizedBy[signer] == address(0)); - } - - /** - * @notice Check if `signer` has not been authorized, and if it has been previously - * authorized that it was authorized by `account`. - * @param account The authorizing account address. - * @param signer The possibly authorized address. - * @return Returns `false` if authorized. Returns `true` otherwise. - */ - function isNotAuthorizedSignerForAnotherAccount(address account, address signer) - internal - view - returns (bool) - { - return (authorizedBy[signer] == address(0) || authorizedBy[signer] == account); - } - - /** - * @notice Authorizes some role of `msg.sender`'s account to another address. - * @param authorized The address to authorize. - * @param v The recovery id of the incoming ECDSA signature. - * @param r Output value r of the ECDSA signature. - * @param s Output value s of the ECDSA signature. - * @dev Fails if the address is already authorized to another account or is an account itself. - * @dev Note that once an address is authorized, it may never be authorized again. - * @dev v, r, s constitute `authorized`'s signature on `msg.sender`. - */ - function authorizeAddress(address authorized, uint8 v, bytes32 r, bytes32 s) private { - address signer = Signatures.getSignerOfAddress(msg.sender, v, r, s); - require(signer == authorized, "Invalid signature"); - - authorize(authorized); - } - - /** - * @notice Returns the address that signed the provided role authorization. - * @param account The `account` property signed over in the EIP712 signature - * @param signer The `signer` property signed over in the EIP712 signature - * @param role The `role` property signed over in the EIP712 signature - * @param v The recovery id of the incoming ECDSA signature. - * @param r Output value r of the ECDSA signature. - * @param s Output value s of the ECDSA signature. - * @return The address that signed the provided role authorization. - */ - function getRoleAuthorizationSigner( - address account, - address signer, - bytes32 role, - uint8 v, - bytes32 r, - bytes32 s - ) public view returns (address) { - bytes32 structHash = keccak256( - abi.encode(EIP712_AUTHORIZE_SIGNER_TYPEHASH, account, signer, role) - ); - return Signatures.getSignerOfTypedDataHash(eip712DomainSeparator, structHash, v, r, s); - } - - /** - * @notice Authorizes a role of `msg.sender`'s account to another address (`authorized`). - * @param authorized The address to authorize. - * @param role The role to authorize. - * @param v The recovery id of the incoming ECDSA signature. - * @param r Output value r of the ECDSA signature. - * @param s Output value s of the ECDSA signature. - * @dev Fails if the address is already authorized to another account or is an account itself. - * @dev Note that this signature is EIP712 compliant over the authorizing `account` - * (`msg.sender`), `signer` (`authorized`) and `role`. - */ - function authorizeAddressWithRole(address authorized, bytes32 role, uint8 v, bytes32 r, bytes32 s) - private - { - address signer = getRoleAuthorizationSigner(msg.sender, authorized, role, v, r, s); - require(signer == authorized, "Invalid signature"); - - authorize(authorized); - } - - /** - * @notice Authorizes an address to `msg.sender`'s account - * @param authorized The address to authorize. - * @dev Fails if the address is already authorized for another account or is an account itself. - */ - function authorize(address authorized) private { - require( - isAccount(msg.sender), - "Unknown account: sender must register with createAccount first" - ); - require( - isNotAccount(authorized) && isNotAuthorizedSignerForAnotherAccount(msg.sender, authorized), - "Cannot re-authorize address or locked gold account for another account" - ); - - authorizedBy[authorized] = msg.sender; - } -} diff --git a/packages/protocol/contracts/common/CalledByVm.sol b/packages/protocol/contracts/common/CalledByVm.sol deleted file mode 100644 index 5ba141b78..000000000 --- a/packages/protocol/contracts/common/CalledByVm.sol +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.5.13 <0.9.0; - -contract CalledByVm { - modifier onlyVm() { - require(msg.sender == address(0), "Only VM can call"); - _; - } -} diff --git a/packages/protocol/contracts/common/Create2.sol b/packages/protocol/contracts/common/Create2.sol deleted file mode 100644 index 08fbc6a88..000000000 --- a/packages/protocol/contracts/common/Create2.sol +++ /dev/null @@ -1,25 +0,0 @@ -pragma solidity ^0.5.13; - -library Create2 { - function computeAddress(address deployer, bytes32 salt, bytes32 initCodeHash) - internal - pure - returns (address) - { - return - address( - uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), deployer, salt, initCodeHash)))) - ); - } - - function deploy(bytes32 salt, bytes memory initCode) internal returns (address) { - address deployedAddress; - assembly { - deployedAddress := create2(0, add(initCode, 32), mload(initCode), salt) - if iszero(extcodesize(deployedAddress)) { - revert(0, 0) - } - } - return deployedAddress; - } -} diff --git a/packages/protocol/contracts/common/ExternalCall.sol b/packages/protocol/contracts/common/ExternalCall.sol deleted file mode 100644 index 1463faee3..000000000 --- a/packages/protocol/contracts/common/ExternalCall.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/utils/Address.sol"; - -library ExternalCall { - /** - * @notice Executes external call. - * @param destination The address to call. - * @param value The CELO value to be sent. - * @param data The data to be sent. - * @return The call return value. - */ - function execute(address destination, uint256 value, bytes memory data) - internal - returns (bytes memory) - { - if (data.length > 0) require(Address.isContract(destination), "Invalid contract address"); - bool success; - bytes memory returnData; - (success, returnData) = destination.call.value(value)(data); - require(success, "Transaction execution failed."); - return returnData; - } -} diff --git a/packages/protocol/contracts/common/ExtractFunctionSignature.sol b/packages/protocol/contracts/common/ExtractFunctionSignature.sol deleted file mode 100644 index c3e41cb23..000000000 --- a/packages/protocol/contracts/common/ExtractFunctionSignature.sol +++ /dev/null @@ -1,15 +0,0 @@ -pragma solidity ^0.5.13; - -library ExtractFunctionSignature { - /** - * @notice Extracts the first four bytes of a byte array. - * @param input The byte array. - * @return The first four bytes of `input`. - */ - function extractFunctionSignature(bytes memory input) internal pure returns (bytes4) { - return (bytes4(input[0]) | - (bytes4(input[1]) >> 8) | - (bytes4(input[2]) >> 16) | - (bytes4(input[3]) >> 24)); - } -} diff --git a/packages/protocol/contracts/common/FeeCurrencyWhitelist.sol b/packages/protocol/contracts/common/FeeCurrencyWhitelist.sol deleted file mode 100644 index 6236eb2a9..000000000 --- a/packages/protocol/contracts/common/FeeCurrencyWhitelist.sol +++ /dev/null @@ -1,81 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./interfaces/IFeeCurrencyWhitelist.sol"; - -import "../common/Initializable.sol"; - -import "../common/interfaces/ICeloVersionedContract.sol"; - -/** - * @title Holds a whitelist of the ERC20+ tokens that can be used to pay for gas - * Not including the native Celo token - */ -contract FeeCurrencyWhitelist is - IFeeCurrencyWhitelist, - Ownable, - Initializable, - ICeloVersionedContract -{ - // Array of all the tokens enabled - address[] public whitelist; - - event FeeCurrencyWhitelisted(address token); - - event FeeCurrencyWhitelistRemoved(address token); - - /** - * @notice Sets initialized == true on implementation contracts - * @param test Set to true to skip implementation initialization - */ - constructor(bool test) public Initializable(test) {} - - /** - * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. - */ - function initialize() external initializer { - _transferOwnership(msg.sender); - } - - /** - * @notice Returns the storage, major, minor, and patch version of the contract. - * @return Storage version of the contract. - * @return Major version of the contract. - * @return Minor version of the contract. - * @return Patch version of the contract. - */ - function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { - return (1, 1, 1, 0); - } - - /** - * @notice Removes a Mento token as enabled fee token. Tokens added with addToken should be - * removed with this function. - * @param tokenAddress The address of the token to remove. - * @param index The index of the token in the whitelist array. - */ - function removeToken(address tokenAddress, uint256 index) public onlyOwner { - require(whitelist[index] == tokenAddress, "Index does not match"); - uint256 length = whitelist.length; - whitelist[index] = whitelist[length - 1]; - whitelist.pop(); - emit FeeCurrencyWhitelistRemoved(tokenAddress); - } - - /** - * @dev Add a token to the whitelist - * @param tokenAddress The address of the token to add. - */ - function addToken(address tokenAddress) external onlyOwner { - whitelist.push(tokenAddress); - emit FeeCurrencyWhitelisted(tokenAddress); - } - - /** - * @return a list of all tokens enabled as gas fee currency. - */ - function getWhitelist() external view returns (address[] memory) { - return whitelist; - } -} diff --git a/packages/protocol/contracts/common/FeeHandler.sol b/packages/protocol/contracts/common/FeeHandler.sol deleted file mode 100644 index 51e9fd855..000000000 --- a/packages/protocol/contracts/common/FeeHandler.sol +++ /dev/null @@ -1,568 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "openzeppelin-solidity/contracts/math/Math.sol"; -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; -import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; -import "openzeppelin-solidity/contracts/utils/EnumerableSet.sol"; - -import "./UsingRegistry.sol"; -import "../common/Freezable.sol"; -import "../common/FixidityLib.sol"; -import "../common/Initializable.sol"; - -import "../common/interfaces/IFeeHandler.sol"; -import "../common/interfaces/IFeeHandlerSeller.sol"; - -// TODO move to IStableToken when it adds method getExchangeRegistryId -import "./interfaces/IStableTokenMento.sol"; -import "../common/interfaces/ICeloVersionedContract.sol"; -import "../common/interfaces/ICeloToken.sol"; -import "../stability/interfaces/ISortedOracles.sol"; - -// Using the minimal required signatures in the interfaces so more contracts could be compatible -import "../common/libraries/ReentrancyGuard.sol"; - -// An implementation of FeeHandler as described in CIP-52 -// See https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0052.md -contract FeeHandler is - Ownable, - Initializable, - UsingRegistry, - ICeloVersionedContract, - Freezable, - IFeeHandler, - ReentrancyGuard -{ - using SafeMath for uint256; - using FixidityLib for FixidityLib.Fraction; - using EnumerableSet for EnumerableSet.AddressSet; - - uint256 public constant FIXED1_UINT = 1000000000000000000000000; // TODO move to FIX and add check - - // Min units that can be burned - uint256 public constant MIN_BURN = 200; - - // last day the daily limits were updated - uint256 public lastLimitDay; - - FixidityLib.Fraction public burnFraction; // 80% - - address public feeBeneficiary; - - uint256 public celoToBeBurned; - - // This mapping can not be public because it contains a FixidityLib.Fraction - // and that'd be only supported with experimental features in this - // compiler version - mapping(address => TokenState) private tokenStates; - - struct TokenState { - address handler; - FixidityLib.Fraction maxSlippage; - // Max amounts that can be burned in a day for a token - uint256 dailySellLimit; - // Max amounts that can be burned today for a token - uint256 currentDaySellLimit; - uint256 toDistribute; - // Historical amounts burned by this contract - uint256 pastBurn; - } - - EnumerableSet.AddressSet private activeTokens; - - event SoldAndBurnedToken(address token, uint256 value); - event DailyLimitSet(address tokenAddress, uint256 newLimit); - event DailyLimitHit(address token, uint256 burning); - event MaxSlippageSet(address token, uint256 maxSlippage); - event DailySellLimitUpdated(uint256 amount); - event FeeBeneficiarySet(address newBeneficiary); - event BurnFractionSet(uint256 fraction); - event TokenAdded(address tokenAddress, address handlerAddress); - event TokenRemoved(address tokenAddress); - - /** - * @notice Sets initialized == true on implementation contracts. - * @param test Set to true to skip implementation initialisation. - */ - constructor(bool test) public Initializable(test) {} - - /** - * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. - */ - function initialize( - address _registryAddress, - address newFeeBeneficiary, - uint256 newBurnFraction, - address[] calldata tokens, - address[] calldata handlers, - uint256[] calldata newLimits, - uint256[] calldata newMaxSlippages - ) external initializer { - require(tokens.length == handlers.length, "handlers length should match tokens length"); - require(tokens.length == newLimits.length, "limits length should match tokens length"); - require( - tokens.length == newMaxSlippages.length, - "maxSlippage length should match tokens length" - ); - - _transferOwnership(msg.sender); - setRegistry(_registryAddress); - _setFeeBeneficiary(newFeeBeneficiary); - _setBurnFraction(newBurnFraction); - - for (uint256 i = 0; i < tokens.length; i++) { - _addToken(tokens[i], handlers[i]); - _setDailySellLimit(tokens[i], newLimits[i]); - _setMaxSplippage(tokens[i], newMaxSlippages[i]); - } - } - - // Without this the contract cant receive Celo as native transfer - function() external payable {} - - /** - @dev Returns the handler address for the specified token. - @param tokenAddress The address of the token for which to return the handler. - @return The address of the handler contract for the specified token. - */ - function getTokenHandler(address tokenAddress) external view returns (address) { - return tokenStates[tokenAddress].handler; - } - - /** - @dev Returns a boolean indicating whether the specified token is active or not. - @param tokenAddress The address of the token for which to retrieve the active status. - @return A boolean representing the active status of the specified token. - */ - function getTokenActive(address tokenAddress) external view returns (bool) { - return activeTokens.contains(tokenAddress); - } - - /** - @dev Returns the maximum slippage percentage for the specified token. - @param tokenAddress The address of the token for which to retrieve the maximum - slippage percentage. - @return The maximum slippage percentage as a uint256 value. - */ - function getTokenMaxSlippage(address tokenAddress) external view returns (uint256) { - return FixidityLib.unwrap(tokenStates[tokenAddress].maxSlippage); - } - - /** - @dev Returns the daily burn limit for the specified token. - @param tokenAddress The address of the token for which to retrieve the daily burn limit. - @return The daily burn limit as a uint256 value. - */ - - function getTokenDailySellLimit(address tokenAddress) external view returns (uint256) { - return tokenStates[tokenAddress].dailySellLimit; - } - - /** - @dev Returns the current daily sell limit for the specified token. - @param tokenAddress The address of the token for which to retrieve the current daily limit. - @return The current daily limit as a uint256 value. - */ - function getTokenCurrentDaySellLimit(address tokenAddress) external view returns (uint256) { - return tokenStates[tokenAddress].currentDaySellLimit; - } - - /** - @dev Returns the amount of tokens available to distribute for the specified token. - @param tokenAddress The address of the token for which to retrieve the amount of - tokens available to distribute. - @return The amount of tokens available to distribute as a uint256 value. - */ - function getTokenToDistribute(address tokenAddress) external view returns (uint256) { - return tokenStates[tokenAddress].toDistribute; - } - - function getActiveTokens() public view returns (address[] memory) { - return activeTokens.values; - } - - /** - @dev Sets the fee beneficiary address to the specified address. - @param beneficiary The address to set as the fee beneficiary. - */ - function setFeeBeneficiary(address beneficiary) external onlyOwner { - return _setFeeBeneficiary(beneficiary); - } - - function _setFeeBeneficiary(address beneficiary) private { - feeBeneficiary = beneficiary; - emit FeeBeneficiarySet(beneficiary); - } - - /** - @dev Sets the burn fraction to the specified value. - @param fraction The value to set as the burn fraction. - */ - function setBurnFraction(uint256 fraction) external onlyOwner { - return _setBurnFraction(fraction); - } - - function _setBurnFraction(uint256 newFraction) private { - FixidityLib.Fraction memory fraction = FixidityLib.wrap(newFraction); - require( - FixidityLib.lte(fraction, FixidityLib.fixed1()), - "Burn fraction must be less than or equal to 1" - ); - burnFraction = fraction; - emit BurnFractionSet(newFraction); - } - - /** - @dev Sets the burn fraction to the specified value. Token has to have a handler set. - @param tokenAddress The address of the token to sell - */ - function sell(address tokenAddress) external { - return _sell(tokenAddress); - } - - /** - @dev Adds a new token to the contract with the specified token and handler addresses. - @param tokenAddress The address of the token to add. - @param handlerAddress The address of the handler contract for the specified token. - */ - function addToken(address tokenAddress, address handlerAddress) external onlyOwner { - _addToken(tokenAddress, handlerAddress); - } - - function _addToken(address tokenAddress, address handlerAddress) private { - require(handlerAddress != address(0), "Can't set handler to zero"); - TokenState storage tokenState = tokenStates[tokenAddress]; - tokenState.handler = handlerAddress; - - activeTokens.add(tokenAddress); - emit TokenAdded(tokenAddress, handlerAddress); - } - - /** - @notice Allows the owner to activate a specified token. - @param tokenAddress The address of the token to be activated. - */ - function activateToken(address tokenAddress) external onlyOwner { - _activateToken(tokenAddress); - } - - function _activateToken(address tokenAddress) private { - TokenState storage tokenState = tokenStates[tokenAddress]; - require( - tokenState.handler != address(0) || - tokenAddress == registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID), - "Handler has to be set to activate token" - ); - activeTokens.add(tokenAddress); - } - - /** - @dev Deactivates the specified token by marking it as inactive. - @param tokenAddress The address of the token to deactivate. - */ - function deactivateToken(address tokenAddress) external onlyOwner { - _deactivateToken(tokenAddress); - } - - function _deactivateToken(address tokenAddress) private { - activeTokens.remove(tokenAddress); - } - - /** - @notice Allows the owner to set a handler contract for a specified token. - @param tokenAddress The address of the token to set the handler for. - @param handlerAddress The address of the handler contract to be set. - */ - function setHandler(address tokenAddress, address handlerAddress) external onlyOwner { - _setHandler(tokenAddress, handlerAddress); - } - - function _setHandler(address tokenAddress, address handlerAddress) private { - require(handlerAddress != address(0), "Can't set handler to zero, use deactivateToken"); - TokenState storage tokenState = tokenStates[tokenAddress]; - tokenState.handler = handlerAddress; - } - - function removeToken(address tokenAddress) external onlyOwner { - _removeToken(tokenAddress); - } - - function _removeToken(address tokenAddress) private { - _deactivateToken(tokenAddress); - TokenState storage tokenState = tokenStates[tokenAddress]; - tokenState.handler = address(0); - emit TokenRemoved(tokenAddress); - } - - function _sell(address tokenAddress) private onlyWhenNotFrozen nonReentrant { - IERC20 token = IERC20(tokenAddress); - - TokenState storage tokenState = tokenStates[tokenAddress]; - require(tokenState.handler != address(0), "Handler has to be set to sell token"); - require( - FixidityLib.unwrap(tokenState.maxSlippage) != 0, - "Max slippage has to be set to sell token" - ); - FixidityLib.Fraction memory balanceToProcess = FixidityLib.newFixed( - token.balanceOf(address(this)).sub(tokenState.toDistribute) - ); - - uint256 balanceToBurn = (burnFraction.multiply(balanceToProcess).fromFixed()); - - tokenState.toDistribute = tokenState.toDistribute.add( - balanceToProcess.fromFixed().sub(balanceToBurn) - ); - - // small numbers cause rounding errors and zero case should be skipped - if (balanceToBurn < MIN_BURN) { - return; - } - - if (dailySellLimitHit(tokenAddress, balanceToBurn)) { - // in case the limit is hit, burn the max possible - balanceToBurn = tokenState.currentDaySellLimit; - emit DailyLimitHit(tokenAddress, balanceToBurn); - } - - token.transfer(tokenState.handler, balanceToBurn); - IFeeHandlerSeller handler = IFeeHandlerSeller(tokenState.handler); - - uint256 celoReceived = handler.sell( - tokenAddress, - registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID), - balanceToBurn, - FixidityLib.unwrap(tokenState.maxSlippage) - ); - - celoToBeBurned = celoToBeBurned.add(celoReceived); - tokenState.pastBurn = tokenState.pastBurn.add(balanceToBurn); - updateLimits(tokenAddress, balanceToBurn); - - emit SoldAndBurnedToken(tokenAddress, balanceToBurn); - } - - /** - @dev Distributes the available tokens for the specified token address to the fee beneficiary. - @param tokenAddress The address of the token for which to distribute the available tokens. - */ - function distribute(address tokenAddress) external { - return _distribute(tokenAddress); - } - - function _distribute(address tokenAddress) private onlyWhenNotFrozen nonReentrant { - require(feeBeneficiary != address(0), "Can't distribute to the zero address"); - IERC20 token = IERC20(tokenAddress); - uint256 tokenBalance = token.balanceOf(address(this)); - - TokenState storage tokenState = tokenStates[tokenAddress]; - require( - tokenState.handler != address(0) || - tokenAddress == registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID), - "Handler has to be set to sell token" - ); - - // safty check to avoid a revert due balance - uint256 balanceToDistribute = Math.min(tokenBalance, tokenState.toDistribute); - - if (balanceToDistribute == 0) { - // don't distribute with zero balance - return; - } - - token.transfer(feeBeneficiary, balanceToDistribute); - tokenState.toDistribute = tokenState.toDistribute.sub(balanceToDistribute); - } - - /** - * @notice Returns the storage, major, minor, and patch version of the contract. - * @return Storage version of the contract. - * @return Major version of the contract. - * @return Minor version of the contract. - * @return Patch version of the contract. - */ - function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { - return (1, 1, 0, 0); - } - - /** - * @notice Allows owner to set max slippage for a token. - * @param token Address of the token to set. - * @param newMax New sllipage to set, as Fixidity fraction. - */ - function setMaxSplippage(address token, uint256 newMax) external onlyOwner { - _setMaxSplippage(token, newMax); - } - - function _setMaxSplippage(address token, uint256 newMax) private { - TokenState storage tokenState = tokenStates[token]; - require(newMax != 0, "Cannot set max slippage to zero"); - tokenState.maxSlippage = FixidityLib.wrap(newMax); - require( - FixidityLib.lte(tokenState.maxSlippage, FixidityLib.fixed1()), - "Splippage must be less than or equal to 1" - ); - emit MaxSlippageSet(token, newMax); - } - - /** - * @notice Allows owner to set the daily burn limit for a token. - * @param token Address of the token to set. - * @param newLimit The new limit to set, in the token units. - */ - function setDailySellLimit(address token, uint256 newLimit) external onlyOwner { - _setDailySellLimit(token, newLimit); - } - - function _setDailySellLimit(address token, uint256 newLimit) private { - TokenState storage tokenState = tokenStates[token]; - tokenState.dailySellLimit = newLimit; - emit DailyLimitSet(token, newLimit); - } - - /** - @dev Burns CELO tokens according to burnFraction. - */ - function burnCelo() external { - return _burnCelo(); - } - - /** - @dev Distributes the available tokens for all registered tokens to the feeBeneficiary. - */ - function distributeAll() external { - return _distributeAll(); - } - - function _distributeAll() private { - for (uint256 i = 0; i < EnumerableSet.length(activeTokens); i++) { - address token = activeTokens.get(i); - _distribute(token); - } - // distribute Celo - _distribute(registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID)); - } - - /** - @dev Distributes the available tokens for all registered tokens to the feeBeneficiary. - */ - function handleAll() external { - return _handleAll(); - } - - function _handleAll() private { - for (uint256 i = 0; i < EnumerableSet.length(activeTokens); i++) { - // calling _handle would trigger may burn Celo and distributions - // that can be just batched at the end - address token = activeTokens.get(i); - _sell(token); - } - _distributeAll(); // distributes Celo as well - _burnCelo(); - } - - /** - @dev Distributes the the token for to the feeBeneficiary. - */ - function handle(address tokenAddress) external { - return _handle(tokenAddress); - } - - function _handle(address tokenAddress) private { - // Celo doesn't have to be exchanged for anything - if (tokenAddress != registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID)) { - _sell(tokenAddress); - } - _burnCelo(); - _distribute(tokenAddress); - _distribute(registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID)); - } - - /** - * @notice Burns all the Celo balance of this contract. - */ - function _burnCelo() private { - TokenState storage tokenState = tokenStates[registry.getAddressForOrDie( - GOLD_TOKEN_REGISTRY_ID - )]; - ICeloToken celo = ICeloToken(registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID)); - - uint256 balanceOfCelo = address(this).balance; - - uint256 balanceToProcess = balanceOfCelo.sub(tokenState.toDistribute).sub(celoToBeBurned); - uint256 currentBalanceToBurn = FixidityLib - .newFixed(balanceToProcess) - .multiply(burnFraction) - .fromFixed(); - uint256 totalBalanceToBurn = currentBalanceToBurn.add(celoToBeBurned); - celo.burn(totalBalanceToBurn); - - celoToBeBurned = 0; - tokenState.toDistribute = tokenState.toDistribute.add( - balanceToProcess.sub(currentBalanceToBurn) - ); - } - - /** - * @param token The address of the token to query. - * @return The amount burned for a token. - */ - function getPastBurnForToken(address token) external view returns (uint256) { - return tokenStates[token].pastBurn; - } - - /** - * @param token The address of the token to query. - * @param amountToBurn The amount of the token to burn. - * @return Returns true if burning amountToBurn would exceed the daily limit. - */ - function dailySellLimitHit(address token, uint256 amountToBurn) public returns (bool) { - TokenState storage tokenState = tokenStates[token]; - - if (tokenState.dailySellLimit == 0) { - // if no limit set, assume uncapped - return false; - } - - uint256 currentDay = now / 1 days; - // Pattern borrowed from Reserve.sol - if (currentDay > lastLimitDay) { - lastLimitDay = currentDay; - tokenState.currentDaySellLimit = tokenState.dailySellLimit; - } - - return amountToBurn >= tokenState.currentDaySellLimit; - } - - /** - * @notice Updates the current day limit for a token. - * @param token The address of the token to query. - * @param amountBurned the amount of the token that was burned. - */ - function updateLimits(address token, uint256 amountBurned) private { - TokenState storage tokenState = tokenStates[token]; - - if (tokenState.dailySellLimit == 0) { - // if no limit set, assume uncapped - return; - } - tokenState.currentDaySellLimit = tokenState.currentDaySellLimit.sub(amountBurned); - emit DailySellLimitUpdated(amountBurned); - } - - /** - * @notice Allows owner to transfer tokens of this contract. It's meant for governance to - trigger use cases not contemplated in this contract. - @param token The address of the token to transfer. - @param recipient The address of the recipient to transfer the tokens to. - @param value The amount of tokens to transfer. - @return A boolean indicating whether the transfer was successful or not. - */ - function transfer(address token, address recipient, uint256 value) - external - onlyOwner - returns (bool) - { - return IERC20(token).transfer(recipient, value); - } -} diff --git a/packages/protocol/contracts/common/FeeHandlerSeller.sol b/packages/protocol/contracts/common/FeeHandlerSeller.sol deleted file mode 100644 index 3e3da4fbe..000000000 --- a/packages/protocol/contracts/common/FeeHandlerSeller.sol +++ /dev/null @@ -1,90 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "../common/FixidityLib.sol"; -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; -import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; -import "./UsingRegistry.sol"; -import "../common/Initializable.sol"; - -// Abstract class for a FeeHandlerSeller, as defined in CIP-52 -// https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0052.md -contract FeeHandlerSeller is Ownable, Initializable, UsingRegistry { - using SafeMath for uint256; - using FixidityLib for FixidityLib.Fraction; - - // Address of the token - // Minimal number of reports in SortedOracles contract - mapping(address => uint256) public minimumReports; - - event MinimumReportsSet(address tokenAddress, uint256 minimumReports); - event TokenSold(address soldTokenAddress, address boughtTokenAddress, uint256 amount); - - function initialize( - address _registryAddress, - address[] calldata tokenAddresses, - uint256[] calldata newMininumReports - ) external initializer { - _transferOwnership(msg.sender); - setRegistry(_registryAddress); - - for (uint256 i = 0; i < tokenAddresses.length; i++) { - _setMinimumReports(tokenAddresses[i], newMininumReports[i]); - } - } - - /** - * @notice Allows owner to set the minimum number of reports required. - * @param newMininumReports The new update minimum number of reports required. - */ - function setMinimumReports(address tokenAddress, uint256 newMininumReports) public onlyOwner { - _setMinimumReports(tokenAddress, newMininumReports); - } - - function _setMinimumReports(address tokenAddress, uint256 newMininumReports) internal { - minimumReports[tokenAddress] = newMininumReports; - emit MinimumReportsSet(tokenAddress, newMininumReports); - } - - /** - @dev Calculates the minimum amount of tokens that should be received for the specified - amount with the given mid-price and maximum slippage. - @param midPriceNumerator The numerator of the mid-price for the token pair. - @param midPriceDenominator The denominator of the mid-price for the token pair. - @param amount The amount of tokens to be exchanged. - @param maxSlippage The maximum slippage percentage as a fraction of the mid-price. - @return The minimum amount of tokens that should be received as a uint256 value. - */ - function calculateMinAmount( - uint256 midPriceNumerator, - uint256 midPriceDenominator, - uint256 amount, - uint256 maxSlippage // as fraction - ) public pure returns (uint256) { - FixidityLib.Fraction memory maxSlippageFraction = FixidityLib.wrap(maxSlippage); - - FixidityLib.Fraction memory price = FixidityLib.newFixedFraction( - midPriceNumerator, - midPriceDenominator - ); - FixidityLib.Fraction memory amountFraction = FixidityLib.newFixed(amount); - FixidityLib.Fraction memory totalAmount = price.multiply(amountFraction); - - return - totalAmount - .subtract(price.multiply(maxSlippageFraction).multiply(amountFraction)) - .fromFixed(); - } - - /** - * @notice Allows owner to transfer tokens of this contract. It's meant for governance to - trigger use cases not contemplated in this contract. - @param token The address of the token to transfer. - @param amount The amount of tokens to transfer. - @param to The address of the recipient to transfer the tokens to. - @return A boolean indicating whether the transfer was successful or not. - */ - function transfer(address token, uint256 amount, address to) external onlyOwner returns (bool) { - return IERC20(token).transfer(to, amount); - } -} diff --git a/packages/protocol/contracts/common/FixidityLib.sol b/packages/protocol/contracts/common/FixidityLib.sol deleted file mode 100644 index 2afccc8a5..000000000 --- a/packages/protocol/contracts/common/FixidityLib.sol +++ /dev/null @@ -1,292 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.5.13 <0.9.0; - -/** - * @title FixidityLib - * @author Gadi Guy, Alberto Cuesta Canada - * @notice This library provides fixed point arithmetic with protection against - * overflow. - * All operations are done with uint256 and the operands must have been created - * with any of the newFrom* functions, which shift the comma digits() to the - * right and check for limits, or with wrap() which expects a number already - * in the internal representation of a fraction. - * When using this library be sure to use maxNewFixed() as the upper limit for - * creation of fixed point numbers. - * @dev All contained functions are pure and thus marked internal to be inlined - * on consuming contracts at compile time for gas efficiency. - */ -library FixidityLib { - struct Fraction { - uint256 value; - } - - /** - * @notice Number of positions that the comma is shifted to the right. - */ - function digits() internal pure returns (uint8) { - return 24; - } - - uint256 private constant FIXED1_UINT = 1000000000000000000000000; - - /** - * @notice This is 1 in the fixed point units used in this library. - * @dev Test fixed1() equals 10^digits() - * Hardcoded to 24 digits. - */ - function fixed1() internal pure returns (Fraction memory) { - return Fraction(FIXED1_UINT); - } - - /** - * @notice Wrap a uint256 that represents a 24-decimal fraction in a Fraction - * struct. - * @param x Number that already represents a 24-decimal fraction. - * @return A Fraction struct with contents x. - */ - function wrap(uint256 x) internal pure returns (Fraction memory) { - return Fraction(x); - } - - /** - * @notice Unwraps the uint256 inside of a Fraction struct. - */ - function unwrap(Fraction memory x) internal pure returns (uint256) { - return x.value; - } - - /** - * @notice The amount of decimals lost on each multiplication operand. - * @dev Test mulPrecision() equals sqrt(fixed1) - */ - function mulPrecision() internal pure returns (uint256) { - return 1000000000000; - } - - /** - * @notice Maximum value that can be converted to fixed point. Optimize for deployment. - * @dev - * Test maxNewFixed() equals maxUint256() / fixed1() - */ - function maxNewFixed() internal pure returns (uint256) { - return 115792089237316195423570985008687907853269984665640564; - } - - /** - * @notice Converts a uint256 to fixed point Fraction - * @dev Test newFixed(0) returns 0 - * Test newFixed(1) returns fixed1() - * Test newFixed(maxNewFixed()) returns maxNewFixed() * fixed1() - * Test newFixed(maxNewFixed()+1) fails - */ - function newFixed(uint256 x) internal pure returns (Fraction memory) { - require(x <= maxNewFixed(), "can't create fixidity number larger than maxNewFixed()"); - return Fraction(x * FIXED1_UINT); - } - - /** - * @notice Converts a uint256 in the fixed point representation of this - * library to a non decimal. All decimal digits will be truncated. - */ - function fromFixed(Fraction memory x) internal pure returns (uint256) { - return x.value / FIXED1_UINT; - } - - /** - * @notice Converts two uint256 representing a fraction to fixed point units, - * equivalent to multiplying dividend and divisor by 10^digits(). - * @param numerator numerator must be <= maxNewFixed() - * @param denominator denominator must be <= maxNewFixed() and denominator can't be 0 - * @dev - * Test newFixedFraction(1,0) fails - * Test newFixedFraction(0,1) returns 0 - * Test newFixedFraction(1,1) returns fixed1() - * Test newFixedFraction(1,fixed1()) returns 1 - */ - function newFixedFraction(uint256 numerator, uint256 denominator) - internal - pure - returns (Fraction memory) - { - Fraction memory convertedNumerator = newFixed(numerator); - Fraction memory convertedDenominator = newFixed(denominator); - return divide(convertedNumerator, convertedDenominator); - } - - /** - * @notice Returns the integer part of a fixed point number. - * @dev - * Test integer(0) returns 0 - * Test integer(fixed1()) returns fixed1() - * Test integer(newFixed(maxNewFixed())) returns maxNewFixed()*fixed1() - */ - function integer(Fraction memory x) internal pure returns (Fraction memory) { - return Fraction((x.value / FIXED1_UINT) * FIXED1_UINT); // Can't overflow - } - - /** - * @notice Returns the fractional part of a fixed point number. - * In the case of a negative number the fractional is also negative. - * @dev - * Test fractional(0) returns 0 - * Test fractional(fixed1()) returns 0 - * Test fractional(fixed1()-1) returns 10^24-1 - */ - function fractional(Fraction memory x) internal pure returns (Fraction memory) { - return Fraction(x.value - (x.value / FIXED1_UINT) * FIXED1_UINT); // Can't overflow - } - - /** - * @notice x+y. - * @dev The maximum value that can be safely used as an addition operator is defined as - * maxFixedAdd = maxUint256()-1 / 2, or - * 57896044618658097711785492504343953926634992332820282019728792003956564819967. - * Test add(maxFixedAdd,maxFixedAdd) equals maxFixedAdd + maxFixedAdd - * Test add(maxFixedAdd+1,maxFixedAdd+1) throws - */ - function add(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) { - uint256 z = x.value + y.value; - require(z >= x.value, "add overflow detected"); - return Fraction(z); - } - - /** - * @notice x-y. - * @dev - * Test subtract(6, 10) fails - */ - function subtract(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) { - require(x.value >= y.value, "substraction underflow detected"); - return Fraction(x.value - y.value); - } - - /** - * @notice x*y. If any of the operators is higher than the max multiplier value it - * might overflow. - * @dev The maximum value that can be safely used as a multiplication operator - * (maxFixedMul) is calculated as sqrt(maxUint256()*fixed1()), - * or 340282366920938463463374607431768211455999999999999 - * Test multiply(0,0) returns 0 - * Test multiply(maxFixedMul,0) returns 0 - * Test multiply(0,maxFixedMul) returns 0 - * Test multiply(fixed1()/mulPrecision(),fixed1()*mulPrecision()) returns fixed1() - * Test multiply(maxFixedMul,maxFixedMul) is around maxUint256() - * Test multiply(maxFixedMul+1,maxFixedMul+1) fails - */ - function multiply(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) { - if (x.value == 0 || y.value == 0) return Fraction(0); - if (y.value == FIXED1_UINT) return x; - if (x.value == FIXED1_UINT) return y; - - // Separate into integer and fractional parts - // x = x1 + x2, y = y1 + y2 - uint256 x1 = integer(x).value / FIXED1_UINT; - uint256 x2 = fractional(x).value; - uint256 y1 = integer(y).value / FIXED1_UINT; - uint256 y2 = fractional(y).value; - - // (x1 + x2) * (y1 + y2) = (x1 * y1) + (x1 * y2) + (x2 * y1) + (x2 * y2) - uint256 x1y1 = x1 * y1; - if (x1 != 0) require(x1y1 / x1 == y1, "overflow x1y1 detected"); - - // x1y1 needs to be multiplied back by fixed1 - // solium-disable-next-line mixedcase - uint256 fixed_x1y1 = x1y1 * FIXED1_UINT; - if (x1y1 != 0) require(fixed_x1y1 / x1y1 == FIXED1_UINT, "overflow x1y1 * fixed1 detected"); - x1y1 = fixed_x1y1; - - uint256 x2y1 = x2 * y1; - if (x2 != 0) require(x2y1 / x2 == y1, "overflow x2y1 detected"); - - uint256 x1y2 = x1 * y2; - if (x1 != 0) require(x1y2 / x1 == y2, "overflow x1y2 detected"); - - x2 = x2 / mulPrecision(); - y2 = y2 / mulPrecision(); - uint256 x2y2 = x2 * y2; - if (x2 != 0) require(x2y2 / x2 == y2, "overflow x2y2 detected"); - - // result = fixed1() * x1 * y1 + x1 * y2 + x2 * y1 + x2 * y2 / fixed1(); - Fraction memory result = Fraction(x1y1); - result = add(result, Fraction(x2y1)); // Add checks for overflow - result = add(result, Fraction(x1y2)); // Add checks for overflow - result = add(result, Fraction(x2y2)); // Add checks for overflow - return result; - } - - /** - * @notice 1/x - * @dev - * Test reciprocal(0) fails - * Test reciprocal(fixed1()) returns fixed1() - * Test reciprocal(fixed1()*fixed1()) returns 1 // Testing how the fractional is truncated - * Test reciprocal(1+fixed1()*fixed1()) returns 0 // Testing how the fractional is truncated - * Test reciprocal(newFixedFraction(1, 1e24)) returns newFixed(1e24) - */ - function reciprocal(Fraction memory x) internal pure returns (Fraction memory) { - require(x.value != 0, "can't call reciprocal(0)"); - return Fraction((FIXED1_UINT * FIXED1_UINT) / x.value); // Can't overflow - } - - /** - * @notice x/y. If the dividend is higher than the max dividend value, it - * might overflow. You can use multiply(x,reciprocal(y)) instead. - * @dev The maximum value that can be safely used as a dividend (maxNewFixed) is defined as - * divide(maxNewFixed,newFixedFraction(1,fixed1())) is around maxUint256(). - * This yields the value 115792089237316195423570985008687907853269984665640564. - * Test maxNewFixed equals maxUint256()/fixed1() - * Test divide(maxNewFixed,1) equals maxNewFixed*(fixed1) - * Test divide(maxNewFixed+1,multiply(mulPrecision(),mulPrecision())) throws - * Test divide(fixed1(),0) fails - * Test divide(maxNewFixed,1) = maxNewFixed*(10^digits()) - * Test divide(maxNewFixed+1,1) throws - */ - function divide(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) { - require(y.value != 0, "can't divide by 0"); - uint256 X = x.value * FIXED1_UINT; - require(X / FIXED1_UINT == x.value, "overflow at divide"); - return Fraction(X / y.value); - } - - /** - * @notice x > y - */ - function gt(Fraction memory x, Fraction memory y) internal pure returns (bool) { - return x.value > y.value; - } - - /** - * @notice x >= y - */ - function gte(Fraction memory x, Fraction memory y) internal pure returns (bool) { - return x.value >= y.value; - } - - /** - * @notice x < y - */ - function lt(Fraction memory x, Fraction memory y) internal pure returns (bool) { - return x.value < y.value; - } - - /** - * @notice x <= y - */ - function lte(Fraction memory x, Fraction memory y) internal pure returns (bool) { - return x.value <= y.value; - } - - /** - * @notice x == y - */ - function equals(Fraction memory x, Fraction memory y) internal pure returns (bool) { - return x.value == y.value; - } - - /** - * @notice x <= 1 - */ - function isProperFraction(Fraction memory x) internal pure returns (bool) { - return lte(x, fixed1()); - } -} diff --git a/packages/protocol/contracts/common/Freezable.sol b/packages/protocol/contracts/common/Freezable.sol deleted file mode 100644 index 44948b678..000000000 --- a/packages/protocol/contracts/common/Freezable.sol +++ /dev/null @@ -1,12 +0,0 @@ -pragma solidity ^0.5.13; - -import "./UsingRegistry.sol"; - -contract Freezable is UsingRegistry { - // onlyWhenNotFrozen functions can only be called when `frozen` is false, otherwise they will - // revert. - modifier onlyWhenNotFrozen() { - require(!getFreezer().isFrozen(address(this)), "can't call when contract is frozen"); - _; - } -} diff --git a/packages/protocol/contracts/common/Freezer.sol b/packages/protocol/contracts/common/Freezer.sol deleted file mode 100644 index 3f476fcc4..000000000 --- a/packages/protocol/contracts/common/Freezer.sol +++ /dev/null @@ -1,36 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./Initializable.sol"; -import "./interfaces/IFreezer.sol"; - -contract Freezer is Ownable, Initializable, IFreezer { - mapping(address => bool) public isFrozen; - - /** - * @notice Sets initialized == true on implementation contracts - * @param test Set to true to skip implementation initialization - */ - constructor(bool test) public Initializable(test) {} - - function initialize() external initializer { - _transferOwnership(msg.sender); - } - - /** - * @notice Freezes the target contract, disabling `onlyWhenNotFrozen` functions. - * @param target The address of the contract to freeze. - */ - function freeze(address target) external onlyOwner { - isFrozen[target] = true; - } - - /** - * @notice Unfreezes the contract, enabling `onlyWhenNotFrozen` functions. - * @param target The address of the contract to freeze. - */ - function unfreeze(address target) external onlyOwner { - isFrozen[target] = false; - } -} diff --git a/packages/protocol/contracts/common/GoldToken.sol b/packages/protocol/contracts/common/GoldToken.sol deleted file mode 100644 index 67e2e48e6..000000000 --- a/packages/protocol/contracts/common/GoldToken.sol +++ /dev/null @@ -1,291 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; - -import "./UsingRegistry.sol"; -import "./CalledByVm.sol"; -import "./Initializable.sol"; -import "./interfaces/ICeloToken.sol"; -import "../common/interfaces/ICeloVersionedContract.sol"; - -contract GoldToken is - Initializable, - CalledByVm, - UsingRegistry, - IERC20, - ICeloToken, - ICeloVersionedContract -{ - using SafeMath for uint256; - - // Address of the TRANSFER precompiled contract. - // solhint-disable state-visibility - address constant TRANSFER = address(0xff - 2); - string constant NAME = "Celo native asset"; - string constant SYMBOL = "CELO"; - uint8 constant DECIMALS = 18; - uint256 internal totalSupply_; - // solhint-enable state-visibility - - mapping(address => mapping(address => uint256)) internal allowed; - - // Burn address is 0xdEaD because truffle is having buggy behaviour with the zero address - address constant BURN_ADDRESS = address(0x000000000000000000000000000000000000dEaD); - - event Transfer(address indexed from, address indexed to, uint256 value); - - event TransferComment(string comment); - - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @notice Sets initialized == true on implementation contracts - * @param test Set to true to skip implementation initialization - */ - constructor(bool test) public Initializable(test) {} - - /** - * @notice Returns the storage, major, minor, and patch version of the contract. - * @return Storage version of the contract. - * @return Major version of the contract. - * @return Minor version of the contract. - * @return Patch version of the contract. - */ - function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { - return (1, 1, 2, 0); - } - - /** - * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. - * @param registryAddress Address of the Registry contract. - */ - function initialize(address registryAddress) external initializer { - totalSupply_ = 0; - _transferOwnership(msg.sender); - setRegistry(registryAddress); - } - - /** - * @notice Transfers CELO from one address to another. - * @param to The address to transfer CELO to. - * @param value The amount of CELO to transfer. - * @return True if the transaction succeeds. - */ - // solhint-disable-next-line no-simple-event-func-name - function transfer(address to, uint256 value) external returns (bool) { - return _transferWithCheck(to, value); - } - - /** - * @notice Transfers CELO from one address to another with a comment. - * @param to The address to transfer CELO to. - * @param value The amount of CELO to transfer. - * @param comment The transfer comment - * @return True if the transaction succeeds. - */ - function transferWithComment(address to, uint256 value, string calldata comment) - external - returns (bool) - { - bool succeeded = _transferWithCheck(to, value); - emit TransferComment(comment); - return succeeded; - } - - /** - * @notice This function allows a user to burn a specific amount of tokens. - Burning is implemented by sending tokens to the burn address. - * @param value: The amount of CELO to burn. - * @return True if burn was successful. - */ - function burn(uint256 value) external returns (bool) { - // not using transferWithCheck as the burn address can potentially be the zero address - return _transfer(BURN_ADDRESS, value); - } - - /** - * @notice Approve a user to transfer CELO on behalf of another user. - * @param spender The address which is being approved to spend CELO. - * @param value The amount of CELO approved to the spender. - * @return True if the transaction succeeds. - */ - function approve(address spender, uint256 value) external returns (bool) { - require(spender != address(0), "cannot set allowance for 0"); - allowed[msg.sender][spender] = value; - emit Approval(msg.sender, spender, value); - return true; - } - - /** - * @notice Increases the allowance of another user. - * @param spender The address which is being approved to spend CELO. - * @param value The increment of the amount of CELO approved to the spender. - * @return True if the transaction succeeds. - */ - function increaseAllowance(address spender, uint256 value) external returns (bool) { - require(spender != address(0), "cannot set allowance for 0"); - uint256 oldValue = allowed[msg.sender][spender]; - uint256 newValue = oldValue.add(value); - allowed[msg.sender][spender] = newValue; - emit Approval(msg.sender, spender, newValue); - return true; - } - - /** - * @notice Decreases the allowance of another user. - * @param spender The address which is being approved to spend CELO. - * @param value The decrement of the amount of CELO approved to the spender. - * @return True if the transaction succeeds. - */ - function decreaseAllowance(address spender, uint256 value) external returns (bool) { - uint256 oldValue = allowed[msg.sender][spender]; - uint256 newValue = oldValue.sub(value); - allowed[msg.sender][spender] = newValue; - emit Approval(msg.sender, spender, newValue); - return true; - } - - /** - * @notice Transfers CELO from one address to another on behalf of a user. - * @param from The address to transfer CELO from. - * @param to The address to transfer CELO to. - * @param value The amount of CELO to transfer. - * @return True if the transaction succeeds. - */ - function transferFrom(address from, address to, uint256 value) external returns (bool) { - require(to != address(0), "transfer attempted to reserved address 0x0"); - require(value <= balanceOf(from), "transfer value exceeded balance of sender"); - require( - value <= allowed[from][msg.sender], - "transfer value exceeded sender's allowance for spender" - ); - - bool success; - (success, ) = TRANSFER.call.value(0).gas(gasleft())(abi.encode(from, to, value)); - require(success, "CELO transfer failed"); - - allowed[from][msg.sender] = allowed[from][msg.sender].sub(value); - emit Transfer(from, to, value); - return true; - } - - /** - * @notice Mints new CELO and gives it to 'to'. - * @param to The account for which to mint tokens. - * @param value The amount of CELO to mint. - */ - function mint(address to, uint256 value) external onlyVm returns (bool) { - if (value == 0) { - return true; - } - - require(to != address(0), "mint attempted to reserved address 0x0"); - totalSupply_ = totalSupply_.add(value); - - bool success; - (success, ) = TRANSFER.call.value(0).gas(gasleft())(abi.encode(address(0), to, value)); - require(success, "CELO transfer failed"); - - emit Transfer(address(0), to, value); - return true; - } - - /** - * @return The name of the CELO token. - */ - function name() external view returns (string memory) { - return NAME; - } - - /** - * @return The symbol of the CELO token. - */ - function symbol() external view returns (string memory) { - return SYMBOL; - } - - /** - * @return The number of decimal places to which CELO is divisible. - */ - function decimals() external view returns (uint8) { - return DECIMALS; - } - - /** - * @return The total amount of CELO in existence, including what the burn address holds. - */ - function totalSupply() external view returns (uint256) { - return totalSupply_; - } - - /** - * @return The total amount of CELO in existence, not including what the burn address holds. - */ - function circulatingSupply() external view returns (uint256) { - return totalSupply_.sub(getBurnedAmount()).sub(balanceOf(address(0))); - } - - /** - * @notice Gets the amount of owner's CELO allowed to be spent by spender. - * @param owner The owner of the CELO. - * @param spender The spender of the CELO. - * @return The amount of CELO owner is allowing spender to spend. - */ - function allowance(address owner, address spender) external view returns (uint256) { - return allowed[owner][spender]; - } - - /** - * @notice Increases the variable for total amount of CELO in existence. - * @param amount The amount to increase counter by - */ - function increaseSupply(uint256 amount) external onlyVm { - totalSupply_ = totalSupply_.add(amount); - } - - /** - * @notice Gets the amount of CELO that has been burned. - * @return The total amount of Celo that has been sent to the burn address. - */ - function getBurnedAmount() public view returns (uint256) { - return balanceOf(BURN_ADDRESS); - } - - /** - * @notice Gets the balance of the specified address. - * @param owner The address to query the balance of. - * @return The balance of the specified address. - */ - function balanceOf(address owner) public view returns (uint256) { - return owner.balance; - } - - /** - * @notice internal CELO transfer from one address to another. - * @param to The address to transfer CELO to. - * @param value The amount of CELO to transfer. - * @return True if the transaction succeeds. - */ - function _transfer(address to, uint256 value) internal returns (bool) { - require(value <= balanceOf(msg.sender), "transfer value exceeded balance of sender"); - - bool success; - (success, ) = TRANSFER.call.value(0).gas(gasleft())(abi.encode(msg.sender, to, value)); - require(success, "CELO transfer failed"); - emit Transfer(msg.sender, to, value); - return true; - } - - /** - * @notice Internal CELO transfer from one address to another. - * @param to The address to transfer CELO to. Zero address will revert. - * @param value The amount of CELO to transfer. - * @return True if the transaction succeeds. - */ - function _transferWithCheck(address to, uint256 value) internal returns (bool) { - require(to != address(0), "transfer attempted to reserved address 0x0"); - return _transfer(to, value); - } -} diff --git a/packages/protocol/contracts/common/Initializable.sol b/packages/protocol/contracts/common/Initializable.sol deleted file mode 100644 index 779e42cb9..000000000 --- a/packages/protocol/contracts/common/Initializable.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.5.13 <0.9.0; - -contract Initializable { - bool public initialized; - - constructor(bool testingDeployment) public { - if (!testingDeployment) { - initialized = true; - } - } - - modifier initializer() { - require(!initialized, "contract already initialized"); - initialized = true; - _; - } -} diff --git a/packages/protocol/contracts/common/InitializableProxy.sol b/packages/protocol/contracts/common/InitializableProxy.sol deleted file mode 100644 index 8d65b8f00..000000000 --- a/packages/protocol/contracts/common/InitializableProxy.sol +++ /dev/null @@ -1,33 +0,0 @@ -pragma solidity ^0.5.13; - -import "./Proxy.sol"; - -/** - * @title A Proxy utilizing the Unstructured Storage pattern. - * @dev This proxy is intended to be used in conjunction with EIP-1167 minimal proxies. - */ -contract InitializableProxy is Proxy { - /** - * @notice Sets proxy ownership to an unrecoverable address. - * @dev This contract is intended to be the target of delegatecalls from EIP-1167 proxies. - * As such, we take precautions here to ensure that this contract can never be pointed to - * an implementation, which would then risk that this contract could be selfdestructed, - * which would "brick" all EIP-1167 clones of this contract. - */ - constructor() public { - // We cannot set the owner to 0x0 as that is both explicitly prevented in `_setOwner`, and as - // that would result in `_initialize` being callable, exposing the very vulnerability this - // constructor is intended to prevent. - _setOwner(address(0x1)); - } - - /** - * @notice Sets the proxy owner if it hasn't already been set. - * @param owner The address allowed to repoint the proxy to a new implementation. - * @dev Note that anyone is allowed to set the proxy owner if it is set to the null address. - */ - function _initialize(address owner) external { - require(_getOwner() == address(0), "Owner already set"); - _setOwner(owner); - } -} diff --git a/packages/protocol/contracts/common/MentoFeeHandlerSeller.sol b/packages/protocol/contracts/common/MentoFeeHandlerSeller.sol deleted file mode 100644 index 34fdf112b..000000000 --- a/packages/protocol/contracts/common/MentoFeeHandlerSeller.sol +++ /dev/null @@ -1,85 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; -import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; - -import "../../lib/mento-core/contracts/interfaces/IExchange.sol"; -import "./interfaces/IStableTokenMento.sol"; - -import "./UsingRegistry.sol"; -import "../common/interfaces/IFeeHandlerSeller.sol"; -import "../stability/interfaces/ISortedOracles.sol"; -import "../common/FixidityLib.sol"; -import "../common/Initializable.sol"; -import "./FeeHandlerSeller.sol"; - -// An implementation of FeeHandlerSeller supporting interfaces compatible with -// Mento -// See https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0052.md -contract MentoFeeHandlerSeller is IFeeHandlerSeller, FeeHandlerSeller { - using SafeMath for uint256; - using FixidityLib for FixidityLib.Fraction; - - /** - * @notice Sets initialized == true on implementation contracts. - * @param test Set to true to skip implementation initialisation. - */ - constructor(bool test) public Initializable(test) {} - - // without this line the contract can't receive native Celo transfers - function() external payable {} - - /** - * @notice Returns the storage, major, minor, and patch version of the contract. - * @return Storage version of the contract. - * @return Major version of the contract. - * @return Minor version of the contract. - * @return Patch version of the contract. - */ - function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { - return (1, 1, 0, 0); - } - - function sell( - address sellTokenAddress, - address buyTokenAddress, - uint256 amount, - uint256 maxSlippage // as fraction, - ) external returns (uint256) { - require( - buyTokenAddress == registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID), - "Buy token can only be gold token" - ); - - IStableTokenMento stableToken = IStableTokenMento(sellTokenAddress); - require(amount <= stableToken.balanceOf(address(this)), "Balance of token to burn not enough"); - - address exchangeAddress = registry.getAddressForOrDie(stableToken.getExchangeRegistryId()); - - IExchange exchange = IExchange(exchangeAddress); - - uint256 minAmount = 0; - - ISortedOracles sortedOracles = getSortedOracles(); - - require( - sortedOracles.numRates(sellTokenAddress) >= minimumReports[sellTokenAddress], - "Number of reports for token not enough" - ); - - (uint256 rateNumerator, uint256 rateDenominator) = sortedOracles.medianRate(sellTokenAddress); - minAmount = calculateMinAmount(rateNumerator, rateDenominator, amount, maxSlippage); - - // TODO an upgrade would be to compare using routers as well - stableToken.approve(exchangeAddress, amount); - exchange.sell(amount, minAmount, false); - - IERC20 goldToken = getGoldToken(); - uint256 celoAmount = goldToken.balanceOf(address(this)); - goldToken.transfer(msg.sender, celoAmount); - - emit TokenSold(sellTokenAddress, buyTokenAddress, amount); - return celoAmount; - } -} diff --git a/packages/protocol/contracts/common/MetaTransactionWallet.sol b/packages/protocol/contracts/common/MetaTransactionWallet.sol deleted file mode 100644 index bb0924475..000000000 --- a/packages/protocol/contracts/common/MetaTransactionWallet.sol +++ /dev/null @@ -1,324 +0,0 @@ -pragma solidity ^0.5.13; -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; -import "solidity-bytes-utils/contracts/BytesLib.sol"; - -import "./interfaces/ICeloVersionedContract.sol"; -import "./interfaces/IMetaTransactionWallet.sol"; -import "./ExternalCall.sol"; -import "./Initializable.sol"; -import "./Signatures.sol"; - -contract MetaTransactionWallet is - IMetaTransactionWallet, - ICeloVersionedContract, - Initializable, - Ownable -{ - using SafeMath for uint256; - using BytesLib for bytes; - - bytes32 public eip712DomainSeparator; - // The EIP712 typehash for ExecuteMetaTransaction, i.e. keccak256( - // "ExecuteMetaTransaction(address destination,uint256 value,bytes data,uint256 nonce)"); - bytes32 public constant EIP712_EXECUTE_META_TRANSACTION_TYPEHASH = ( - 0x509c6e92324b7214543573524d0bb493d654d3410fa4f4937b3d2f4a903edd33 - ); - uint256 public nonce; - address public signer; - address public guardian; - - event SignerSet(address indexed signer); - event GuardianSet(address indexed guardian); - event WalletRecovered(address indexed newSigner); - event EIP712DomainSeparatorSet(bytes32 eip712DomainSeparator); - event Deposit(address indexed sender, uint256 value); - event TransactionExecution( - address indexed destination, - uint256 value, - bytes data, - bytes returnData - ); - event MetaTransactionExecution( - address indexed destination, - uint256 value, - bytes data, - uint256 indexed nonce, - bytes returnData - ); - - // onlyGuardian functions can only be called when the guardian is not the zero address and - // the caller is the guardian. - modifier onlyGuardian() { - // Note that if the guardian is not set (e.g. its address 0), this require statement will fail. - require(guardian == msg.sender, "Caller is not the guardian"); - _; - } - - /** - * @notice Sets initialized == true on implementation contracts - * @param test Set to true to skip implementation initialization - */ - constructor(bool test) public Initializable(test) {} - - /** - * @dev Fallback function allows to deposit ether. - */ - function() external payable { - if (msg.value > 0) emit Deposit(msg.sender, msg.value); - } - - /** - * @notice Returns the storage, major, minor, and patch version of the contract. - * @return Storage version of the contract. - * @return Major version of the contract. - * @return Minor version of the contract. - * @return Patch version of the contract. - */ - function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { - return (1, 1, 1, 1); - } - - /** - * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. - * @param _signer The address authorized to execute transactions via this wallet. - */ - function initialize(address _signer) external initializer { - _setSigner(_signer); - setEip712DomainSeparator(); - // MetaTransactionWallet owns itself, which necessitates that all onlyOwner functions - // be called via executeTransaction or executeMetaTransaction. - // If the signer was the owner, onlyOwner functions would not be callable via - // meta-transactions. - _transferOwnership(address(this)); - } - - /** - * @notice Transfers control of the wallet to a new signer. - * @param _signer The address authorized to execute transactions via this wallet. - */ - function setSigner(address _signer) external onlyOwner { - _setSigner(_signer); - } - - /** - * @notice Sets the wallet's guardian address. - * @param _guardian The address authorized to change the wallet's signer - */ - function setGuardian(address _guardian) external onlyOwner { - guardian = _guardian; - emit GuardianSet(guardian); - } - - /** - * @notice Changes the wallet's signer - * @param newSigner The new signer address - */ - function recoverWallet(address newSigner) external onlyGuardian { - _setSigner(newSigner); - emit WalletRecovered(newSigner); - } - - /** - * @notice Sets the EIP-712 domain separator. - * @dev Should be called every time the wallet is upgraded to a new version. - */ - function setEip712DomainSeparator() public { - uint256 id; - assembly { - id := chainid - } - // Note: `version` is the storage.major part of this contract's version (an - // increase to either of these could mean backwards incompatibilities). - eip712DomainSeparator = keccak256( - abi.encode( - keccak256( - "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" - ), - keccak256(bytes("MetaTransactionWallet")), - keccak256("1.1"), - id, - address(this) - ) - ); - emit EIP712DomainSeparatorSet(eip712DomainSeparator); - } - - /** - * @notice Returns the struct hash of the MetaTransaction - * @param destination The address to which the meta-transaction is to be sent. - * @param value The CELO value to be sent with the meta-transaction. - * @param data The data to be sent with the meta-transaction. - * @param _nonce The nonce for this meta-transaction local to this wallet. - * @return The digest of the provided meta-transaction. - */ - function _getMetaTransactionStructHash( - address destination, - uint256 value, - bytes memory data, - uint256 _nonce - ) internal view returns (bytes32) { - return - keccak256( - abi.encode( - EIP712_EXECUTE_META_TRANSACTION_TYPEHASH, - destination, - value, - keccak256(data), - _nonce - ) - ); - } - - /** - * @notice Returns the digest of the provided meta-transaction, to be signed by `sender`. - * @param destination The address to which the meta-transaction is to be sent. - * @param value The CELO value to be sent with the meta-transaction. - * @param data The data to be sent with the meta-transaction. - * @param _nonce The nonce for this meta-transaction local to this wallet. - * @return The digest of the provided meta-transaction. - */ - function getMetaTransactionDigest( - address destination, - uint256 value, - bytes calldata data, - uint256 _nonce - ) external view returns (bytes32) { - bytes32 structHash = _getMetaTransactionStructHash(destination, value, data, _nonce); - return Signatures.toEthSignedTypedDataHash(eip712DomainSeparator, structHash); - } - - /** - * @notice Returns the address that signed the provided meta-transaction. - * @param destination The address to which the meta-transaction is to be sent. - * @param value The CELO value to be sent with the meta-transaction. - * @param data The data to be sent with the meta-transaction. - * @param _nonce The nonce for this meta-transaction local to this wallet. - * @param v The recovery id of the ECDSA signature of the meta-transaction. - * @param r Output value r of the ECDSA signature. - * @param s Output value s of the ECDSA signature. - * @return The address that signed the provided meta-transaction. - */ - function getMetaTransactionSigner( - address destination, - uint256 value, - bytes memory data, - uint256 _nonce, - uint8 v, - bytes32 r, - bytes32 s - ) public view returns (address) { - bytes32 structHash = _getMetaTransactionStructHash(destination, value, data, _nonce); - return Signatures.getSignerOfTypedDataHash(eip712DomainSeparator, structHash, v, r, s); - } - - /** - * @notice Executes a meta-transaction on behalf of the signer. - * @param destination The address to which the meta-transaction is to be sent. - * @param value The CELO value to be sent with the meta-transaction. - * @param data The data to be sent with the meta-transaction. - * @param v The recovery id of the ECDSA signature of the meta-transaction. - * @param r Output value r of the ECDSA signature. - * @param s Output value s of the ECDSA signature. - * @return The return value of the meta-transaction execution. - */ - function executeMetaTransaction( - address destination, - uint256 value, - bytes calldata data, - uint8 v, - bytes32 r, - bytes32 s - ) external returns (bytes memory) { - address _signer = getMetaTransactionSigner(destination, value, data, nonce, v, r, s); - require(_signer == signer, "Invalid meta-transaction signer"); - nonce = nonce.add(1); - bytes memory returnData = ExternalCall.execute(destination, value, data); - emit MetaTransactionExecution(destination, value, data, nonce.sub(1), returnData); - return returnData; - } - - /** - * @notice Executes a transaction on behalf of the signer.` - * @param destination The address to which the transaction is to be sent. - * @param value The CELO value to be sent with the transaction. - * @param data The data to be sent with the transaction. - * @return The return value of the transaction execution. - */ - function executeTransaction(address destination, uint256 value, bytes memory data) - public - returns (bytes memory) - { - // Allowing the owner to call execute transaction allows, when the contract is self-owned, - // for the signer to sign and execute a batch of transactions via a meta-transaction. - require(msg.sender == signer || msg.sender == owner(), "Invalid transaction sender"); - bytes memory returnData = ExternalCall.execute(destination, value, data); - emit TransactionExecution(destination, value, data, returnData); - return returnData; - } - - /** - * @notice Executes multiple transactions on behalf of the signer.` - * @param destinations The address to which each transaction is to be sent. - * @param values The CELO value to be sent with each transaction. - * @param data The concatenated data to be sent in each transaction. - * @param dataLengths The length of each transaction's data. - * @return All transactions appended as bytes - * @return An array of the length - * of each transaction output which will be 0 if a transaction had no output - */ - function executeTransactions( - address[] calldata destinations, - uint256[] calldata values, - bytes calldata data, - uint256[] calldata dataLengths - ) external returns (bytes memory, uint256[] memory) { - require( - destinations.length == values.length && values.length == dataLengths.length, - "Input arrays must be same length" - ); - - bytes memory returnValues; - uint256[] memory returnLengths = new uint256[](destinations.length); - uint256 dataPosition = 0; - for (uint256 i = 0; i < destinations.length; i = i.add(1)) { - bytes memory returnVal = executeTransaction( - destinations[i], - values[i], - sliceData(data, dataPosition, dataLengths[i]) - ); - returnValues = abi.encodePacked(returnValues, returnVal); - returnLengths[i] = returnVal.length; - dataPosition = dataPosition.add(dataLengths[i]); - } - - require(dataPosition == data.length, "data cannot have extra bytes appended"); - return (returnValues, returnLengths); - } - - /** - * @notice Returns a slice from a byte array. - * @param data The byte array. - * @param start The start index of the slice to take. - * @param length The length of the slice to take. - * @return A slice from a byte array. - */ - function sliceData(bytes memory data, uint256 start, uint256 length) - internal - returns (bytes memory) - { - // When length == 0 bytes.slice does not seem to always return an empty byte array. - bytes memory sliced; - if (length > 0) { - sliced = data.slice(start, length); - } - return sliced; - } - - function _setSigner(address _signer) internal { - require(_signer != address(0), "cannot assign zero address as signer"); - signer = _signer; - emit SignerSet(signer); - } - -} diff --git a/packages/protocol/contracts/common/MetaTransactionWalletDeployer.sol b/packages/protocol/contracts/common/MetaTransactionWalletDeployer.sol deleted file mode 100644 index 8db335e68..000000000 --- a/packages/protocol/contracts/common/MetaTransactionWalletDeployer.sol +++ /dev/null @@ -1,35 +0,0 @@ -pragma solidity ^0.5.13; - -import "./interfaces/ICeloVersionedContract.sol"; -import "./interfaces/IMetaTransactionWalletDeployer.sol"; -import "./proxies/MetaTransactionWalletProxy.sol"; - -contract MetaTransactionWalletDeployer is IMetaTransactionWalletDeployer, ICeloVersionedContract { - event WalletDeployed(address indexed owner, address indexed wallet, address implementation); - - /** - * @notice Returns the storage, major, minor, and patch version of the contract. - * @return Storage version of the contract. - * @return Major version of the contract. - * @return Minor version of the contract. - * @return Patch version of the contract. - */ - function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { - return (1, 1, 0, 3); - } - - /** - * @notice Used to deploy a MetaTransactionWalletProxy, set the implementation, - * initialize, transfer ownership and emit an event. - * @param owner The external account which will act as signer and owner of the proxy - * @param implementation The address of the implementation which the proxy will point to - * @param initCallData calldata pointing to a method on implementation used to initialize - */ - function deploy(address owner, address implementation, bytes calldata initCallData) external { - MetaTransactionWalletProxy proxy = new MetaTransactionWalletProxy(); - proxy._setAndInitializeImplementation(implementation, initCallData); - proxy._transferOwnership(owner); - - emit WalletDeployed(owner, address(proxy), implementation); - } -} diff --git a/packages/protocol/contracts/common/MultiSig.sol b/packages/protocol/contracts/common/MultiSig.sol deleted file mode 100644 index f569d2a76..000000000 --- a/packages/protocol/contracts/common/MultiSig.sol +++ /dev/null @@ -1,390 +0,0 @@ -pragma solidity ^0.5.13; -/* solhint-disable no-inline-assembly, avoid-low-level-calls, func-name-mixedcase, func-order */ - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; - -import "./ExternalCall.sol"; -import "./Initializable.sol"; - -/** - * @title Multisignature wallet - Allows multiple parties to agree on transactions before - * execution. - * @author Stefan George - - * @dev NOTE: This contract has its limitations and is not viable for every - * multi-signature setup. On a case by case basis, evaluate whether this is the - * correct contract for your use case. - * In particular, this contract doesn't have an atomic "add owners and increase - * requirement" operation. - * This can be tricky, for example, in a situation where a MultiSig starts out - * owned by a single owner. Safely increasing the owner set and requirement at - * the same time is not trivial. One way to work around this situation is to - * first add a second address controlled by the original owner, increase the - * requirement, and then replace the auxillary address with the intended second - * owner. - * Again, this is just one example, in general make sure to verify this contract - * will support your intended usage. The goal of this contract is to offer a - * simple, minimal multi-signature API that's easy to understand even for novice - * Solidity users. - */ -contract MultiSig is Initializable { - using SafeMath for uint256; - /* - * Events - */ - event Confirmation(address indexed sender, uint256 indexed transactionId); - event Revocation(address indexed sender, uint256 indexed transactionId); - event Submission(uint256 indexed transactionId); - event Execution(uint256 indexed transactionId, bytes returnData); - event Deposit(address indexed sender, uint256 value); - event OwnerAddition(address indexed owner); - event OwnerRemoval(address indexed owner); - event RequirementChange(uint256 required); - event InternalRequirementChange(uint256 internalRequired); - - /* - * Constants - */ - uint256 public constant MAX_OWNER_COUNT = 50; - - /* - * Storage - */ - mapping(uint256 => Transaction) public transactions; - mapping(uint256 => mapping(address => bool)) public confirmations; - mapping(address => bool) public isOwner; - address[] public owners; - uint256 public required; - uint256 public internalRequired; - uint256 public transactionCount; - - struct Transaction { - address destination; - uint256 value; - bytes data; - bool executed; - } - - /** - * @notice Sets initialized == true on implementation contracts - * @param test Set to true to skip implementation initialization - */ - constructor(bool test) public Initializable(test) {} - - /* - * Modifiers - */ - modifier onlyWallet() { - require(msg.sender == address(this), "msg.sender was not multisig wallet"); - _; - } - - modifier ownerDoesNotExist(address owner) { - require(!isOwner[owner], "owner already existed"); - _; - } - - modifier ownerExists(address owner) { - require(isOwner[owner], "owner does not exist"); - _; - } - - modifier transactionExists(uint256 transactionId) { - require(transactions[transactionId].destination != address(0), "transaction does not exist"); - _; - } - - modifier confirmed(uint256 transactionId, address owner) { - require(confirmations[transactionId][owner], "transaction was not confirmed for owner"); - _; - } - - modifier notConfirmed(uint256 transactionId, address owner) { - require(!confirmations[transactionId][owner], "transaction was already confirmed for owner"); - _; - } - - modifier notExecuted(uint256 transactionId) { - require(!transactions[transactionId].executed, "transaction was executed already"); - _; - } - - modifier notNull(address _address) { - require(_address != address(0), "address was null"); - _; - } - - modifier validRequirement(uint256 ownerCount, uint256 _required) { - require( - ownerCount <= MAX_OWNER_COUNT && _required <= ownerCount && _required != 0 && ownerCount != 0, - "invalid requirement" - ); - _; - } - - /// @dev Fallback function allows to deposit ether. - function() external payable { - if (msg.value > 0) emit Deposit(msg.sender, msg.value); - } - - /* - * Public functions - */ - /// @dev Contract constructor sets initial owners and required number of confirmations. - /// @param _owners List of initial owners. - /// @param _required Number of required confirmations for external transactions. - /// @param _internalRequired Number of required confirmations for internal transactions. - function initialize(address[] calldata _owners, uint256 _required, uint256 _internalRequired) - external - initializer - validRequirement(_owners.length, _required) - validRequirement(_owners.length, _internalRequired) - { - for (uint256 i = 0; i < _owners.length; i = i.add(1)) { - require( - !isOwner[_owners[i]] && _owners[i] != address(0), - "owner was null or already given owner status" - ); - isOwner[_owners[i]] = true; - } - owners = _owners; - required = _required; - internalRequired = _internalRequired; - } - - /// @dev Allows to add a new owner. Transaction has to be sent by wallet. - /// @param owner Address of new owner. - function addOwner(address owner) - external - onlyWallet - ownerDoesNotExist(owner) - notNull(owner) - validRequirement(owners.length.add(1), internalRequired) - { - isOwner[owner] = true; - owners.push(owner); - emit OwnerAddition(owner); - } - - /// @dev Allows to remove an owner. Transaction has to be sent by wallet. - /// @param owner Address of owner. - function removeOwner(address owner) external onlyWallet ownerExists(owner) { - isOwner[owner] = false; - for (uint256 i = 0; i < owners.length.sub(1); i = i.add(1)) - if (owners[i] == owner) { - owners[i] = owners[owners.length.sub(1)]; - break; - } - owners.length = owners.length.sub(1); - if (required > owners.length) changeRequirement(owners.length); - if (internalRequired > owners.length) changeInternalRequirement(owners.length); - emit OwnerRemoval(owner); - } - - /// @dev Allows to replace an owner with a new owner. Transaction has to be sent by wallet. - /// @param owner Address of owner to be replaced. - /// @param newOwner Address of new owner. - function replaceOwner(address owner, address newOwner) - external - onlyWallet - ownerExists(owner) - notNull(newOwner) - ownerDoesNotExist(newOwner) - { - for (uint256 i = 0; i < owners.length; i = i.add(1)) - if (owners[i] == owner) { - owners[i] = newOwner; - break; - } - isOwner[owner] = false; - isOwner[newOwner] = true; - emit OwnerRemoval(owner); - emit OwnerAddition(newOwner); - } - - /// @dev Allows to change the number of required confirmations. Transaction has to be sent by - /// wallet. - /// @param _required Number of required confirmations. - function changeRequirement(uint256 _required) - public - onlyWallet - validRequirement(owners.length, _required) - { - required = _required; - emit RequirementChange(_required); - } - - /// @dev Allows to change the number of required confirmations. Transaction has to be sent by - /// wallet. - /// @param _internalRequired Number of required confirmations for interal txs. - function changeInternalRequirement(uint256 _internalRequired) - public - onlyWallet - validRequirement(owners.length, _internalRequired) - { - internalRequired = _internalRequired; - emit InternalRequirementChange(_internalRequired); - } - - /// @dev Allows an owner to submit and confirm a transaction. - /// @param destination Transaction target address. - /// @param value Transaction ether value. - /// @param data Transaction data payload. - /// @return Returns transaction ID. - function submitTransaction(address destination, uint256 value, bytes calldata data) - external - returns (uint256 transactionId) - { - transactionId = addTransaction(destination, value, data); - confirmTransaction(transactionId); - } - - /// @dev Allows an owner to confirm a transaction. - /// @param transactionId Transaction ID. - function confirmTransaction(uint256 transactionId) - public - ownerExists(msg.sender) - transactionExists(transactionId) - notConfirmed(transactionId, msg.sender) - { - confirmations[transactionId][msg.sender] = true; - emit Confirmation(msg.sender, transactionId); - if (isConfirmed(transactionId)) { - executeTransaction(transactionId); - } - } - - /// @dev Allows an owner to revoke a confirmation for a transaction. - /// @param transactionId Transaction ID. - function revokeConfirmation(uint256 transactionId) - external - ownerExists(msg.sender) - confirmed(transactionId, msg.sender) - notExecuted(transactionId) - { - confirmations[transactionId][msg.sender] = false; - emit Revocation(msg.sender, transactionId); - } - - /// @dev Allows anyone to execute a confirmed transaction. - /// @param transactionId Transaction ID. - function executeTransaction(uint256 transactionId) - public - ownerExists(msg.sender) - confirmed(transactionId, msg.sender) - notExecuted(transactionId) - { - require(isConfirmed(transactionId), "Transaction not confirmed."); - Transaction storage txn = transactions[transactionId]; - txn.executed = true; - bytes memory returnData = ExternalCall.execute(txn.destination, txn.value, txn.data); - emit Execution(transactionId, returnData); - } - - /// @dev Returns the confirmation status of a transaction. - /// @param transactionId Transaction ID. - /// @return Confirmation status. - function isConfirmed(uint256 transactionId) public view returns (bool) { - uint256 count = 0; - for (uint256 i = 0; i < owners.length; i = i.add(1)) { - if (confirmations[transactionId][owners[i]]) count = count.add(1); - bool isInternal = transactions[transactionId].destination == address(this); - if ((isInternal && count == internalRequired) || (!isInternal && count == required)) - return true; - } - return false; - } - - /* - * Internal functions - */ - /// @dev Adds a new transaction to the transaction mapping, if transaction does not exist yet. - /// @param destination Transaction target address. - /// @param value Transaction ether value. - /// @param data Transaction data payload. - /// @return Returns transaction ID. - function addTransaction(address destination, uint256 value, bytes memory data) - internal - notNull(destination) - returns (uint256 transactionId) - { - transactionId = transactionCount; - transactions[transactionId] = Transaction({ - destination: destination, - value: value, - data: data, - executed: false - }); - transactionCount = transactionCount.add(1); - emit Submission(transactionId); - } - - /* - * Web3 call functions - */ - /// @dev Returns number of confirmations of a transaction. - /// @param transactionId Transaction ID. - /// @return Number of confirmations. - function getConfirmationCount(uint256 transactionId) external view returns (uint256 count) { - for (uint256 i = 0; i < owners.length; i = i.add(1)) - if (confirmations[transactionId][owners[i]]) count = count.add(1); - } - - /// @dev Returns total number of transactions after filters are applied. - /// @param pending Include pending transactions. - /// @param executed Include executed transactions. - /// @return Total number of transactions after filters are applied. - function getTransactionCount(bool pending, bool executed) external view returns (uint256 count) { - for (uint256 i = 0; i < transactionCount; i = i.add(1)) - if ((pending && !transactions[i].executed) || (executed && transactions[i].executed)) - count = count.add(1); - } - - /// @dev Returns list of owners. - /// @return List of owner addresses. - function getOwners() external view returns (address[] memory) { - return owners; - } - - /// @dev Returns array with owner addresses, which confirmed transaction. - /// @param transactionId Transaction ID. - /// @return Returns array of owner addresses. - function getConfirmations(uint256 transactionId) - external - view - returns (address[] memory _confirmations) - { - address[] memory confirmationsTemp = new address[](owners.length); - uint256 count = 0; - uint256 i; - for (i = 0; i < owners.length; i = i.add(1)) - if (confirmations[transactionId][owners[i]]) { - confirmationsTemp[count] = owners[i]; - count = count.add(1); - } - _confirmations = new address[](count); - for (i = 0; i < count; i = i.add(1)) _confirmations[i] = confirmationsTemp[i]; - } - - /// @dev Returns list of transaction IDs in defined range. - /// @param from Index start position of transaction array. - /// @param to Index end position of transaction array. - /// @param pending Include pending transactions. - /// @param executed Include executed transactions. - /// @return Returns array of transaction IDs. - function getTransactionIds(uint256 from, uint256 to, bool pending, bool executed) - external - view - returns (uint256[] memory _transactionIds) - { - uint256[] memory transactionIdsTemp = new uint256[](transactionCount); - uint256 count = 0; - uint256 i; - for (i = 0; i < transactionCount; i = i.add(1)) - if ((pending && !transactions[i].executed) || (executed && transactions[i].executed)) { - transactionIdsTemp[count] = i; - count = count.add(1); - } - _transactionIds = new uint256[](to.sub(from)); - for (i = from; i < to; i = i.add(1)) _transactionIds[i.sub(from)] = transactionIdsTemp[i]; - } -} diff --git a/packages/protocol/contracts/common/Proxy.sol b/packages/protocol/contracts/common/Proxy.sol deleted file mode 100644 index 889ad2540..000000000 --- a/packages/protocol/contracts/common/Proxy.sol +++ /dev/null @@ -1,163 +0,0 @@ -pragma solidity ^0.5.13; -/* solhint-disable no-inline-assembly, no-complex-fallback, avoid-low-level-calls */ - -import "openzeppelin-solidity/contracts/utils/Address.sol"; - -/** - * @title A Proxy utilizing the Unstructured Storage pattern. - */ -contract Proxy { - // Used to store the address of the owner. - bytes32 private constant OWNER_POSITION = bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1); - // Used to store the address of the implementation contract. - bytes32 private constant IMPLEMENTATION_POSITION = bytes32( - uint256(keccak256("eip1967.proxy.implementation")) - 1 - ); - - event OwnerSet(address indexed owner); - event ImplementationSet(address indexed implementation); - - constructor() public { - _setOwner(msg.sender); - } - - /** - * @notice Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(msg.sender == _getOwner(), "sender was not owner"); - _; - } - - /** - * @notice Delegates calls to the implementation contract. - */ - function() external payable { - bytes32 implementationPosition = IMPLEMENTATION_POSITION; - - address implementationAddress; - - // Load the address of the implementation contract from an explicit storage slot. - assembly { - implementationAddress := sload(implementationPosition) - } - - // Avoid checking if address is a contract or executing delegated call when - // implementation address is 0x0 - require(implementationAddress != address(0), "No Implementation set"); - require(Address.isContract(implementationAddress), "Invalid contract address"); - - assembly { - // Extract the position of the transaction data (i.e. function ID and arguments). - let newCallDataPosition := mload(0x40) - mstore(0x40, add(newCallDataPosition, calldatasize)) - calldatacopy(newCallDataPosition, 0, calldatasize) - - // Call the smart contract at `implementationAddress` in the context of the proxy contract, - // with the same msg.sender and value. - let delegatecallSuccess := delegatecall( - gas, - implementationAddress, - newCallDataPosition, - calldatasize, - 0, - 0 - ) - - // Copy the return value of the call so it can be returned. - let returnDataSize := returndatasize - let returnDataPosition := mload(0x40) - mstore(0x40, add(returnDataPosition, returnDataSize)) - returndatacopy(returnDataPosition, 0, returnDataSize) - - // Revert or return depending on whether or not the call was successful. - switch delegatecallSuccess - case 0 { - revert(returnDataPosition, returnDataSize) - } - default { - return(returnDataPosition, returnDataSize) - } - } - } - - /** - * @notice Transfers ownership of Proxy to a new owner. - * @param newOwner Address of the new owner account. - */ - function _transferOwnership(address newOwner) external onlyOwner { - _setOwner(newOwner); - } - - /** - * @notice Sets the address of the implementation contract and calls into it. - * @param implementation Address of the new target contract. - * @param callbackData The abi-encoded function call to perform in the implementation - * contract. - * @dev Throws if the initialization callback fails. - * @dev If the target contract does not need initialization, use - * setImplementation instead. - */ - function _setAndInitializeImplementation(address implementation, bytes calldata callbackData) - external - payable - onlyOwner - { - _setImplementation(implementation); - bool success; - bytes memory returnValue; - (success, returnValue) = implementation.delegatecall(callbackData); - require(success, "initialization callback failed"); - } - - /** - * @notice Returns the implementation address. - */ - function _getImplementation() external view returns (address implementation) { - bytes32 implementationPosition = IMPLEMENTATION_POSITION; - // Load the address of the implementation contract from an explicit storage slot. - assembly { - implementation := sload(implementationPosition) - } - } - - /** - * @notice Sets the address of the implementation contract. - * @param implementation Address of the new target contract. - * @dev If the target contract needs to be initialized, call - * setAndInitializeImplementation instead. - */ - function _setImplementation(address implementation) public onlyOwner { - bytes32 implementationPosition = IMPLEMENTATION_POSITION; - - require(Address.isContract(implementation), "Invalid contract address"); - - // Store the address of the implementation contract in an explicit storage slot. - assembly { - sstore(implementationPosition, implementation) - } - - emit ImplementationSet(implementation); - } - - /** - * @notice Returns the Proxy owner's address. - */ - function _getOwner() public view returns (address owner) { - bytes32 position = OWNER_POSITION; - // Load the address of the contract owner from an explicit storage slot. - assembly { - owner := sload(position) - } - } - - function _setOwner(address newOwner) internal { - require(newOwner != address(0), "owner cannot be 0"); - bytes32 position = OWNER_POSITION; - // Store the address of the contract owner in an explicit storage slot. - assembly { - sstore(position, newOwner) - } - emit OwnerSet(newOwner); - } -} diff --git a/packages/protocol/contracts/common/ProxyCloneFactory.sol b/packages/protocol/contracts/common/ProxyCloneFactory.sol deleted file mode 100644 index e24fe9184..000000000 --- a/packages/protocol/contracts/common/ProxyCloneFactory.sol +++ /dev/null @@ -1,64 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./InitializableProxy.sol"; - -/** - * @title A factory for deploying EIP-1167 clones of upgradable Proxy contracts. - */ -contract ProxyCloneFactory is Ownable { - // The address of the Proxy implementation to clone. - address public proxyImplementationAddress; - event ProxyCloneCreated(address proxyClone); - - /** - * @notice Sets the address of the Proxy implementation to clone. - * @param _proxyImplementationAddress The address of the Proxy implementation to clone. - */ - function setImplementationAddress(address _proxyImplementationAddress) external onlyOwner { - proxyImplementationAddress = _proxyImplementationAddress; - } - - // TODO: Upgrade solc version and import from OpenZeppelin instead. - /** - * @notice Creates an EIP-1167 style clone of the specified `_proxyImplementationAddress`. - * @param _proxyImplementationAddress The address of the Proxy implementation to clone. - * @return The address of the clone. - * @dev Copied from OpenZeppelin. - */ - function clone(address _proxyImplementationAddress) internal returns (address instance) { - // solhint-disable-next-line no-inline-assembly - assembly { - let ptr := mload(0x40) - mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000) - mstore(add(ptr, 0x14), shl(0x60, _proxyImplementationAddress)) - mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000) - instance := create(0, ptr, 0x37) - } - require(instance != address(0), "ERC1167: create failed"); - } - - /** - * @notice Creates an EIP-1167 style clone of a Proxy contract, points the Proxy to an - * implementation and initializes it. - * @dev Grants ownership of the deployed proxy to itself, allowing the proxy to invoke - * its own administrative functions if the logic contract permits (use extra caution - * with implementations that permit arbitrary function calls). - * @param implementation The address to point the Proxy to. - * @param initCallData The function to call on the implementation and the corresponding args. - */ - function deploy(address implementation, bytes calldata initCallData) external { - // Cast to prevent compiler from complaining about the output of clone() not being payable. - InitializableProxy proxyClone = InitializableProxy( - address(uint160(clone(proxyImplementationAddress))) - ); - proxyClone._initialize(address(this)); - proxyClone._setAndInitializeImplementation(implementation, initCallData); - // TODO(asa): In the current version of Komenci we transfer proxy ownership to the user. - // Need to decide which to do. - proxyClone._transferOwnership(address(proxyClone)); - emit ProxyCloneCreated(address(proxyClone)); - } -} diff --git a/packages/protocol/contracts/common/Registry.sol b/packages/protocol/contracts/common/Registry.sol deleted file mode 100644 index 9e89bd895..000000000 --- a/packages/protocol/contracts/common/Registry.sol +++ /dev/null @@ -1,101 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./interfaces/IRegistry.sol"; -import "./Initializable.sol"; - -/** - * @title Routes identifiers to addresses. - */ -contract Registry is IRegistry, Ownable, Initializable { - using SafeMath for uint256; - - mapping(bytes32 => address) public registry; - - event RegistryUpdated(string identifier, bytes32 indexed identifierHash, address indexed addr); - - /** - * @notice Sets initialized == true on implementation contracts - * @param test Set to true to skip implementation initialization - */ - constructor(bool test) public Initializable(test) {} - - /** - * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. - */ - function initialize() external initializer { - _transferOwnership(msg.sender); - } - - /** - * @notice Associates the given address with the given identifier. - * @param identifier Identifier of contract whose address we want to set. - * @param addr Address of contract. - */ - function setAddressFor(string calldata identifier, address addr) external onlyOwner { - bytes32 identifierHash = keccak256(abi.encodePacked(identifier)); - registry[identifierHash] = addr; - emit RegistryUpdated(identifier, identifierHash, addr); - } - - /** - * @notice Gets address associated with the given identifierHash. - * @param identifierHash Identifier hash of contract whose address we want to look up. - * @dev Throws if address not set. - */ - function getAddressForOrDie(bytes32 identifierHash) external view returns (address) { - require(registry[identifierHash] != address(0), "identifier has no registry entry"); - return registry[identifierHash]; - } - - /** - * @notice Gets address associated with the given identifierHash. - * @param identifierHash Identifier hash of contract whose address we want to look up. - */ - function getAddressFor(bytes32 identifierHash) external view returns (address) { - return registry[identifierHash]; - } - - /** - * @notice Gets address associated with the given identifier. - * @param identifier Identifier of contract whose address we want to look up. - * @dev Throws if address not set. - */ - function getAddressForStringOrDie(string calldata identifier) external view returns (address) { - bytes32 identifierHash = keccak256(abi.encodePacked(identifier)); - require(registry[identifierHash] != address(0), "identifier has no registry entry"); - return registry[identifierHash]; - } - - /** - * @notice Gets address associated with the given identifier. - * @param identifier Identifier of contract whose address we want to look up. - */ - function getAddressForString(string calldata identifier) external view returns (address) { - bytes32 identifierHash = keccak256(abi.encodePacked(identifier)); - return registry[identifierHash]; - } - - /** - * @notice Iterates over provided array of identifiers, getting the address for each. - * Returns true if `sender` matches the address of one of the provided identifiers. - * @param identifierHashes Array of hashes of approved identifiers. - * @param sender Address in question to verify membership. - * @return True if `sender` corresponds to the address of any of `identifiers` - * registry entries. - */ - function isOneOf(bytes32[] calldata identifierHashes, address sender) - external - view - returns (bool) - { - for (uint256 i = 0; i < identifierHashes.length; i = i.add(1)) { - if (registry[identifierHashes[i]] == sender) { - return true; - } - } - return false; - } -} diff --git a/packages/protocol/contracts/common/Signatures.sol b/packages/protocol/contracts/common/Signatures.sol deleted file mode 100644 index 9d80692a3..000000000 --- a/packages/protocol/contracts/common/Signatures.sol +++ /dev/null @@ -1,84 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/cryptography/ECDSA.sol"; - -library Signatures { - /** - * @notice Given a signed address, returns the signer of the address. - * @param message The address that was signed. - * @param v The recovery id of the incoming ECDSA signature. - * @param r Output value r of the ECDSA signature. - * @param s Output value s of the ECDSA signature. - */ - function getSignerOfAddress(address message, uint8 v, bytes32 r, bytes32 s) - public - pure - returns (address) - { - bytes32 hash = keccak256(abi.encodePacked(message)); - return getSignerOfMessageHash(hash, v, r, s); - } - - /** - * @notice Given a message hash, returns the signer of the address. - * @param messageHash The hash of a message. - * @param v The recovery id of the incoming ECDSA signature. - * @param r Output value r of the ECDSA signature. - * @param s Output value s of the ECDSA signature. - */ - function getSignerOfMessageHash(bytes32 messageHash, uint8 v, bytes32 r, bytes32 s) - public - pure - returns (address) - { - bytes memory signature = new bytes(65); - // Concatenate (r, s, v) into signature. - assembly { - mstore(add(signature, 32), r) - mstore(add(signature, 64), s) - mstore8(add(signature, 96), v) - } - bytes32 prefixedHash = ECDSA.toEthSignedMessageHash(messageHash); - return ECDSA.recover(prefixedHash, signature); - } - - /** - * @notice Given a domain separator and a structHash, construct the typed data hash - * @param eip712DomainSeparator Context specific domain separator - * @param structHash hash of the typed data struct - * @return The EIP712 typed data hash - */ - function toEthSignedTypedDataHash(bytes32 eip712DomainSeparator, bytes32 structHash) - public - pure - returns (bytes32) - { - return keccak256(abi.encodePacked("\x19\x01", eip712DomainSeparator, structHash)); - } - - /** - * @notice Given a domain separator and a structHash and a signature return the signer - * @param eip712DomainSeparator Context specific domain separator - * @param structHash hash of the typed data struct - * @param v The recovery id of the incoming ECDSA signature. - * @param r Output value r of the ECDSA signature. - * @param s Output value s of the ECDSA signature. - */ - function getSignerOfTypedDataHash( - bytes32 eip712DomainSeparator, - bytes32 structHash, - uint8 v, - bytes32 r, - bytes32 s - ) public pure returns (address) { - bytes memory signature = new bytes(65); - // Concatenate (r, s, v) into signature. - assembly { - mstore(add(signature, 32), r) - mstore(add(signature, 64), s) - mstore8(add(signature, 96), v) - } - bytes32 prefixedHash = toEthSignedTypedDataHash(eip712DomainSeparator, structHash); - return ECDSA.recover(prefixedHash, signature); - } -} diff --git a/packages/protocol/contracts/common/UniswapFeeHandlerSeller.sol b/packages/protocol/contracts/common/UniswapFeeHandlerSeller.sol deleted file mode 100644 index b4d7aed60..000000000 --- a/packages/protocol/contracts/common/UniswapFeeHandlerSeller.sol +++ /dev/null @@ -1,213 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; -import "openzeppelin-solidity/contracts/utils/EnumerableSet.sol"; -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; -import "openzeppelin-solidity/contracts/math/Math.sol"; - -import "./UsingRegistry.sol"; - -import "../common/interfaces/IFeeHandlerSeller.sol"; -import "../stability/interfaces/ISortedOracles.sol"; -import "../common/FixidityLib.sol"; -import "../common/Initializable.sol"; -import "./FeeHandlerSeller.sol"; - -import "../uniswap/interfaces/IUniswapV2RouterMin.sol"; -import "../uniswap/interfaces/IUniswapV2FactoryMin.sol"; - -// An implementation of FeeHandlerSeller supporting interfaces compatible with -// Uniswap V2 API -// See https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0052.md -contract UniswapFeeHandlerSeller is IFeeHandlerSeller, FeeHandlerSeller { - using SafeMath for uint256; - using FixidityLib for FixidityLib.Fraction; - using EnumerableSet for EnumerableSet.AddressSet; - - uint256 constant MAX_TIMESTAMP_BLOCK_EXCHANGE = 20; - uint256 constant MAX_NUMBER_ROUTERS_PER_TOKEN = 3; - mapping(address => EnumerableSet.AddressSet) private routerAddresses; - - event ReceivedQuote(address indexed tokneAddress, address indexed router, uint256 quote); - event RouterUsed(address router); - event RouterAddressSet(address token, address router); - event RouterAddressRemoved(address token, address router); - - /** - * @notice Sets initialized == true on implementation contracts. - * @param test Set to true to skip implementation initialisation. - */ - constructor(bool test) public Initializable(test) {} - - // without this line the contract can't receive native Celo transfers - function() external payable {} - - /** - * @notice Returns the storage, major, minor, and patch version of the contract. - * @return Storage version of the contract. - * @return Major version of the contract. - * @return Minor version of the contract. - * @return Patch version of the contract. - */ - function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { - return (1, 1, 0, 0); - } - - /** - * @notice Allows owner to set the router for a token. - * @param token Address of the token to set. - * @param router The new router. - */ - function setRouter(address token, address router) external onlyOwner { - _setRouter(token, router); - } - - function _setRouter(address token, address router) private { - require(router != address(0), "Router can't be address zero"); - routerAddresses[token].add(router); - require( - routerAddresses[token].values.length <= MAX_NUMBER_ROUTERS_PER_TOKEN, - "Max number of routers reached" - ); - emit RouterAddressSet(token, router); - } - - /** - * @notice Allows owner to remove a router for a token. - * @param token Address of the token. - * @param router Address of the router to remove. - */ - function removeRouter(address token, address router) external onlyOwner { - routerAddresses[token].remove(router); - emit RouterAddressRemoved(token, router); - } - - /** - * @notice Get the list of routers for a token. - * @param token The address of the token to query. - * @return An array of all the allowed router. - */ - function getRoutersForToken(address token) external view returns (address[] memory) { - return routerAddresses[token].values; - } - - /** - * @dev Calculates the minimum amount of tokens that can be received for a given amount of sell tokens, - taking into account the slippage and the rates of the sell token and CELO token on the Uniswap V2 pair. - * @param sellTokenAddress The address of the sell token. - * @param maxSlippage The maximum slippage allowed. - * @param amount The amount of sell tokens to be traded. - * @param bestRouter The Uniswap V2 router with the best price. - * @return The minimum amount of tokens that can be received. - */ - function calculateAllMinAmount( - address sellTokenAddress, - uint256 maxSlippage, - uint256 amount, - IUniswapV2RouterMin bestRouter - ) private view returns (uint256) { - ISortedOracles sortedOracles = getSortedOracles(); - uint256 minReports = minimumReports[sellTokenAddress]; - - require( - sortedOracles.numRates(sellTokenAddress) >= minReports, - "Number of reports for token not enough" - ); - - uint256 minimalSortedOracles = 0; - // if minimumReports for this token is zero, assume the check is not needed - if (minReports > 0) { - (uint256 rateNumerator, uint256 rateDenominator) = sortedOracles.medianRate(sellTokenAddress); - - minimalSortedOracles = calculateMinAmount( - rateNumerator, - rateDenominator, - amount, - maxSlippage - ); - } - - IERC20 celoToken = getGoldToken(); - address pair = IUniswapV2FactoryMin(bestRouter.factory()).getPair( - sellTokenAddress, - address(celoToken) - ); - uint256 minAmountPair = calculateMinAmount( - IERC20(sellTokenAddress).balanceOf(pair), - celoToken.balanceOf(pair), - amount, - maxSlippage - ); - - return Math.max(minAmountPair, minimalSortedOracles); - } - - // This function explicitly defines few variables because it was getting error "stack too deep" - function sell( - address sellTokenAddress, - address buyTokenAddress, - uint256 amount, - uint256 maxSlippage // as fraction, - ) external returns (uint256) { - require( - buyTokenAddress == registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID), - "Buy token can only be gold token" - ); - - require( - routerAddresses[sellTokenAddress].values.length > 0, - "routerAddresses should be non empty" - ); - - // An improvement to this function would be to allow the user to pass a path as argument - // and if it generates a better outcome that the ones enabled that gets used - // and the user gets a reward - - IERC20 celoToken = getGoldToken(); - - IUniswapV2RouterMin bestRouter; - uint256 bestRouterQuote = 0; - - address[] memory path = new address[](2); - - path[0] = sellTokenAddress; - path[1] = address(celoToken); - - for (uint256 i = 0; i < routerAddresses[sellTokenAddress].values.length; i++) { - address poolAddress = routerAddresses[sellTokenAddress].get(i); - IUniswapV2RouterMin router = IUniswapV2RouterMin(poolAddress); - - // Using the second return value becuase it's the last argument, - // the previous values show how many tokens are exchanged in each path - // so the first value would be equivalent to balanceToBurn - uint256 wouldGet = router.getAmountsOut(amount, path)[1]; - - emit ReceivedQuote(sellTokenAddress, poolAddress, wouldGet); - if (wouldGet > bestRouterQuote) { - bestRouterQuote = wouldGet; - bestRouter = router; - } - } - - require(bestRouterQuote != 0, "Can't exchange with zero quote"); - - uint256 minAmount = 0; - minAmount = calculateAllMinAmount(sellTokenAddress, maxSlippage, amount, bestRouter); - - IERC20(sellTokenAddress).approve(address(bestRouter), amount); - bestRouter.swapExactTokensForTokens( - amount, - minAmount, - path, - address(this), - block.timestamp + MAX_TIMESTAMP_BLOCK_EXCHANGE - ); - - uint256 celoAmount = celoToken.balanceOf(address(this)); - celoToken.transfer(msg.sender, celoAmount); - emit RouterUsed(address(bestRouter)); - emit TokenSold(sellTokenAddress, buyTokenAddress, amount); - return celoAmount; - } -} diff --git a/packages/protocol/contracts/common/UsingPrecompiles.sol b/packages/protocol/contracts/common/UsingPrecompiles.sol deleted file mode 100644 index 596bb94cc..000000000 --- a/packages/protocol/contracts/common/UsingPrecompiles.sol +++ /dev/null @@ -1,273 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "../common/interfaces/ICeloVersionedContract.sol"; - -contract UsingPrecompiles { - using SafeMath for uint256; - - address constant TRANSFER = address(0xff - 2); - address constant FRACTION_MUL = address(0xff - 3); - address constant PROOF_OF_POSSESSION = address(0xff - 4); - address constant GET_VALIDATOR = address(0xff - 5); - address constant NUMBER_VALIDATORS = address(0xff - 6); - address constant EPOCH_SIZE = address(0xff - 7); - address constant BLOCK_NUMBER_FROM_HEADER = address(0xff - 8); - address constant HASH_HEADER = address(0xff - 9); - address constant GET_PARENT_SEAL_BITMAP = address(0xff - 10); - address constant GET_VERIFIED_SEAL_BITMAP = address(0xff - 11); - - /** - * @notice calculate a * b^x for fractions a, b to `decimals` precision - * @param aNumerator Numerator of first fraction - * @param aDenominator Denominator of first fraction - * @param bNumerator Numerator of exponentiated fraction - * @param bDenominator Denominator of exponentiated fraction - * @param exponent exponent to raise b to - * @param _decimals precision - * @return Numerator of the computed quantity (not reduced). - * @return Denominator of the computed quantity (not reduced). - */ - function fractionMulExp( - uint256 aNumerator, - uint256 aDenominator, - uint256 bNumerator, - uint256 bDenominator, - uint256 exponent, - uint256 _decimals - ) public view returns (uint256, uint256) { - require(aDenominator != 0 && bDenominator != 0, "a denominator is zero"); - uint256 returnNumerator; - uint256 returnDenominator; - bool success; - bytes memory out; - (success, out) = FRACTION_MUL.staticcall( - abi.encodePacked(aNumerator, aDenominator, bNumerator, bDenominator, exponent, _decimals) - ); - require(success, "error calling fractionMulExp precompile"); - returnNumerator = getUint256FromBytes(out, 0); - returnDenominator = getUint256FromBytes(out, 32); - return (returnNumerator, returnDenominator); - } - - /** - * @notice Returns the current epoch size in blocks. - * @return The current epoch size in blocks. - */ - function getEpochSize() public view returns (uint256) { - bytes memory out; - bool success; - (success, out) = EPOCH_SIZE.staticcall(abi.encodePacked()); - require(success, "error calling getEpochSize precompile"); - return getUint256FromBytes(out, 0); - } - - /** - * @notice Returns the epoch number at a block. - * @param blockNumber Block number where epoch number is calculated. - * @return Epoch number. - */ - function getEpochNumberOfBlock(uint256 blockNumber) public view returns (uint256) { - return epochNumberOfBlock(blockNumber, getEpochSize()); - } - - /** - * @notice Returns the epoch number at a block. - * @return Current epoch number. - */ - function getEpochNumber() public view returns (uint256) { - return getEpochNumberOfBlock(block.number); - } - - /** - * @notice Returns the epoch number at a block. - * @param blockNumber Block number where epoch number is calculated. - * @param epochSize The epoch size in blocks. - * @return Epoch number. - */ - function epochNumberOfBlock(uint256 blockNumber, uint256 epochSize) - internal - pure - returns (uint256) - { - // Follows GetEpochNumber from celo-blockchain/blob/master/consensus/istanbul/utils.go - uint256 epochNumber = blockNumber / epochSize; - if (blockNumber % epochSize == 0) { - return epochNumber; - } else { - return epochNumber.add(1); - } - } - - /** - * @notice Gets a validator address from the current validator set. - * @param index Index of requested validator in the validator set. - * @return Address of validator at the requested index. - */ - // TODO: (soloseng) add to precompiles - function validatorSignerAddressFromCurrentSet(uint256 index) public view returns (address) { - bytes memory out; - bool success; - (success, out) = GET_VALIDATOR.staticcall(abi.encodePacked(index, uint256(block.number))); - require(success, "error calling validatorSignerAddressFromCurrentSet precompile"); - return address(getUint256FromBytes(out, 0)); - } - - /** - * @notice Gets a validator address from the validator set at the given block number. - * @param index Index of requested validator in the validator set. - * @param blockNumber Block number to retrieve the validator set from. - * @return Address of validator at the requested index. - */ - function validatorSignerAddressFromSet(uint256 index, uint256 blockNumber) - public - view - returns (address) - { - bytes memory out; - bool success; - (success, out) = GET_VALIDATOR.staticcall(abi.encodePacked(index, blockNumber)); - require(success, "error calling validatorSignerAddressFromSet precompile"); - return address(getUint256FromBytes(out, 0)); - } - - /** - * @notice Gets the size of the current elected validator set. - * @return Size of the current elected validator set. - */ - // TODO:(soloseng) add to precompiles. - function numberValidatorsInCurrentSet() public view returns (uint256) { - bytes memory out; - bool success; - (success, out) = NUMBER_VALIDATORS.staticcall(abi.encodePacked(uint256(block.number))); - require(success, "error calling numberValidatorsInCurrentSet precompile"); - return getUint256FromBytes(out, 0); - } - - /** - * @notice Gets the size of the validator set that must sign the given block number. - * @param blockNumber Block number to retrieve the validator set from. - * @return Size of the validator set. - */ - function numberValidatorsInSet(uint256 blockNumber) public view returns (uint256) { - bytes memory out; - bool success; - (success, out) = NUMBER_VALIDATORS.staticcall(abi.encodePacked(blockNumber)); - require(success, "error calling numberValidatorsInSet precompile"); - return getUint256FromBytes(out, 0); - } - - /** - * @notice Checks a BLS proof of possession. - * @param sender The address signed by the BLS key to generate the proof of possession. - * @param blsKey The BLS public key that the validator is using for consensus, should pass proof - * of possession. 48 bytes. - * @param blsPop The BLS public key proof-of-possession, which consists of a signature on the - * account address. 96 bytes. - * @return True upon success. - */ - function checkProofOfPossession(address sender, bytes memory blsKey, bytes memory blsPop) - public - view - returns (bool) - { - bool success; - (success, ) = PROOF_OF_POSSESSION.staticcall(abi.encodePacked(sender, blsKey, blsPop)); - return success; - } - - /** - * @notice Parses block number out of header. - * @param header RLP encoded header - * @return Block number. - */ - function getBlockNumberFromHeader(bytes memory header) public view returns (uint256) { - bytes memory out; - bool success; - (success, out) = BLOCK_NUMBER_FROM_HEADER.staticcall(abi.encodePacked(header)); - require(success, "error calling getBlockNumberFromHeader precompile"); - return getUint256FromBytes(out, 0); - } - - /** - * @notice Computes hash of header. - * @param header RLP encoded header - * @return Header hash. - */ - function hashHeader(bytes memory header) public view returns (bytes32) { - bytes memory out; - bool success; - (success, out) = HASH_HEADER.staticcall(abi.encodePacked(header)); - require(success, "error calling hashHeader precompile"); - return getBytes32FromBytes(out, 0); - } - - /** - * @notice Gets the parent seal bitmap from the header at the given block number. - * @param blockNumber Block number to retrieve. Must be within 4 epochs of the current number. - * @return Bitmap parent seal with set bits at indices corresponding to signing validators. - */ - function getParentSealBitmap(uint256 blockNumber) public view returns (bytes32) { - bytes memory out; - bool success; - (success, out) = GET_PARENT_SEAL_BITMAP.staticcall(abi.encodePacked(blockNumber)); - require(success, "error calling getParentSealBitmap precompile"); - return getBytes32FromBytes(out, 0); - } - - /** - * @notice Verifies the BLS signature on the header and returns the seal bitmap. - * The validator set used for verification is retrieved based on the parent hash field of the - * header. If the parent hash is not in the blockchain, verification fails. - * @param header RLP encoded header - * @return Bitmap parent seal with set bits at indices correspoinding to signing validators. - */ - function getVerifiedSealBitmapFromHeader(bytes memory header) public view returns (bytes32) { - bytes memory out; - bool success; - (success, out) = GET_VERIFIED_SEAL_BITMAP.staticcall(abi.encodePacked(header)); - require(success, "error calling getVerifiedSealBitmapFromHeader precompile"); - return getBytes32FromBytes(out, 0); - } - - /** - * @notice Converts bytes to uint256. - * @param bs byte[] data - * @param start offset into byte data to convert - * @return uint256 data - */ - function getUint256FromBytes(bytes memory bs, uint256 start) internal pure returns (uint256) { - return uint256(getBytes32FromBytes(bs, start)); - } - - /** - * @notice Converts bytes to bytes32. - * @param bs byte[] data - * @param start offset into byte data to convert - * @return bytes32 data - */ - function getBytes32FromBytes(bytes memory bs, uint256 start) internal pure returns (bytes32) { - require(bs.length >= start.add(32), "slicing out of range"); - bytes32 x; - assembly { - x := mload(add(bs, add(start, 32))) - } - return x; - } - - /** - * @notice Returns the minimum number of required signers for a given block number. - * @dev Computed in celo-blockchain as int(math.Ceil(float64(2*valSet.Size()) / 3)) - */ - function minQuorumSize(uint256 blockNumber) public view returns (uint256) { - return numberValidatorsInSet(blockNumber).mul(2).add(2).div(3); - } - - /** - * @notice Computes byzantine quorum from current validator set size - * @return Byzantine quorum of validators. - */ - function minQuorumSizeInCurrentSet() public view returns (uint256) { - return minQuorumSize(block.number); - } -} diff --git a/packages/protocol/contracts/common/UsingRegistry.sol b/packages/protocol/contracts/common/UsingRegistry.sol deleted file mode 100644 index 30563c5ca..000000000 --- a/packages/protocol/contracts/common/UsingRegistry.sol +++ /dev/null @@ -1,131 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; -import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; - -import "./interfaces/IAccounts.sol"; -import "./interfaces/IFeeCurrencyWhitelist.sol"; -import "./interfaces/IFreezer.sol"; -import "./interfaces/IRegistry.sol"; - -import "../governance/interfaces/IElection.sol"; -import "../governance/interfaces/IGovernance.sol"; -import "../governance/interfaces/ILockedGold.sol"; -import "../governance/interfaces/IValidators.sol"; - -import "../identity/interfaces/IRandom.sol"; -import "../identity/interfaces/IAttestations.sol"; - -import "../../lib/mento-core/contracts/interfaces/IExchange.sol"; -import "../../lib/mento-core/contracts/interfaces/IReserve.sol"; -import "../../lib/mento-core/contracts/interfaces/IStableToken.sol"; -import "../stability/interfaces/ISortedOracles.sol"; - -contract UsingRegistry is Ownable { - event RegistrySet(address indexed registryAddress); - - // solhint-disable state-visibility - bytes32 constant ACCOUNTS_REGISTRY_ID = keccak256(abi.encodePacked("Accounts")); - bytes32 constant ATTESTATIONS_REGISTRY_ID = keccak256(abi.encodePacked("Attestations")); - bytes32 constant DOWNTIME_SLASHER_REGISTRY_ID = keccak256(abi.encodePacked("DowntimeSlasher")); - bytes32 constant DOUBLE_SIGNING_SLASHER_REGISTRY_ID = keccak256( - abi.encodePacked("DoubleSigningSlasher") - ); - bytes32 constant ELECTION_REGISTRY_ID = keccak256(abi.encodePacked("Election")); - bytes32 constant EXCHANGE_REGISTRY_ID = keccak256(abi.encodePacked("Exchange")); - bytes32 constant FEE_CURRENCY_WHITELIST_REGISTRY_ID = keccak256( - abi.encodePacked("FeeCurrencyWhitelist") - ); - bytes32 constant FREEZER_REGISTRY_ID = keccak256(abi.encodePacked("Freezer")); - bytes32 constant GOLD_TOKEN_REGISTRY_ID = keccak256(abi.encodePacked("GoldToken")); - bytes32 constant GOVERNANCE_REGISTRY_ID = keccak256(abi.encodePacked("Governance")); - bytes32 constant GOVERNANCE_SLASHER_REGISTRY_ID = keccak256( - abi.encodePacked("GovernanceSlasher") - ); - bytes32 constant LOCKED_GOLD_REGISTRY_ID = keccak256(abi.encodePacked("LockedGold")); - bytes32 constant RESERVE_REGISTRY_ID = keccak256(abi.encodePacked("Reserve")); - bytes32 constant RANDOM_REGISTRY_ID = keccak256(abi.encodePacked("Random")); - bytes32 constant SORTED_ORACLES_REGISTRY_ID = keccak256(abi.encodePacked("SortedOracles")); - bytes32 constant STABLE_TOKEN_REGISTRY_ID = keccak256(abi.encodePacked("StableToken")); - bytes32 constant VALIDATORS_REGISTRY_ID = keccak256(abi.encodePacked("Validators")); - // solhint-enable state-visibility - - IRegistry public registry; - - modifier onlyRegisteredContract(bytes32 identifierHash) { - require(registry.getAddressForOrDie(identifierHash) == msg.sender, "only registered contract"); - _; - } - - modifier onlyRegisteredContracts(bytes32[] memory identifierHashes) { - require(registry.isOneOf(identifierHashes, msg.sender), "only registered contracts"); - _; - } - - /** - * @notice Updates the address pointing to a Registry contract. - * @param registryAddress The address of a registry contract for routing to other contracts. - */ - function setRegistry(address registryAddress) public onlyOwner { - require(registryAddress != address(0), "Cannot register the null address"); - registry = IRegistry(registryAddress); - emit RegistrySet(registryAddress); - } - - function getAccounts() internal view returns (IAccounts) { - return IAccounts(registry.getAddressForOrDie(ACCOUNTS_REGISTRY_ID)); - } - - function getAttestations() internal view returns (IAttestations) { - return IAttestations(registry.getAddressForOrDie(ATTESTATIONS_REGISTRY_ID)); - } - - function getElection() internal view returns (IElection) { - return IElection(registry.getAddressForOrDie(ELECTION_REGISTRY_ID)); - } - - function getExchange() internal view returns (IExchange) { - return IExchange(registry.getAddressForOrDie(EXCHANGE_REGISTRY_ID)); - } - - function getFeeCurrencyWhitelistRegistry() internal view returns (IFeeCurrencyWhitelist) { - return IFeeCurrencyWhitelist(registry.getAddressForOrDie(FEE_CURRENCY_WHITELIST_REGISTRY_ID)); - } - - function getFreezer() internal view returns (IFreezer) { - return IFreezer(registry.getAddressForOrDie(FREEZER_REGISTRY_ID)); - } - - function getGoldToken() internal view returns (IERC20) { - return IERC20(registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID)); - } - - function getGovernance() internal view returns (IGovernance) { - return IGovernance(registry.getAddressForOrDie(GOVERNANCE_REGISTRY_ID)); - } - - function getLockedGold() internal view returns (ILockedGold) { - return ILockedGold(registry.getAddressForOrDie(LOCKED_GOLD_REGISTRY_ID)); - } - - function getRandom() internal view returns (IRandom) { - return IRandom(registry.getAddressForOrDie(RANDOM_REGISTRY_ID)); - } - - function getReserve() internal view returns (IReserve) { - return IReserve(registry.getAddressForOrDie(RESERVE_REGISTRY_ID)); - } - - function getSortedOracles() internal view returns (ISortedOracles) { - return ISortedOracles(registry.getAddressForOrDie(SORTED_ORACLES_REGISTRY_ID)); - } - - function getStableToken() internal view returns (IStableToken) { - return IStableToken(registry.getAddressForOrDie(STABLE_TOKEN_REGISTRY_ID)); - } - - function getValidators() internal view returns (IValidators) { - return IValidators(registry.getAddressForOrDie(VALIDATORS_REGISTRY_ID)); - } -} diff --git a/packages/protocol/contracts/common/UsingRegistryV2.sol b/packages/protocol/contracts/common/UsingRegistryV2.sol deleted file mode 100644 index 8b41d4dcf..000000000 --- a/packages/protocol/contracts/common/UsingRegistryV2.sol +++ /dev/null @@ -1,171 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; -import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; - -import "./interfaces/IAccounts.sol"; -import "./interfaces/IFeeCurrencyWhitelist.sol"; -import "./interfaces/IFreezer.sol"; -import "./interfaces/IRegistry.sol"; - -import "../governance/interfaces/IElection.sol"; -import "../governance/interfaces/IGovernance.sol"; -import "../governance/interfaces/ILockedGold.sol"; -import "../governance/interfaces/IValidators.sol"; - -import "../identity/interfaces/IRandom.sol"; -import "../identity/interfaces/IAttestations.sol"; -import "../identity/interfaces/IFederatedAttestations.sol"; - -import "../../lib/mento-core/contracts/interfaces/IExchange.sol"; -import "../../lib/mento-core/contracts/interfaces/IReserve.sol"; -import "../../lib/mento-core/contracts/interfaces/IStableToken.sol"; -import "../stability/interfaces/ISortedOracles.sol"; - -contract UsingRegistryV2 { - address internal constant registryAddress = 0x000000000000000000000000000000000000ce10; - IRegistry public constant registryContract = IRegistry(registryAddress); - - bytes32 internal constant ACCOUNTS_REGISTRY_ID = keccak256(abi.encodePacked("Accounts")); - bytes32 internal constant ATTESTATIONS_REGISTRY_ID = keccak256(abi.encodePacked("Attestations")); - bytes32 internal constant DOWNTIME_SLASHER_REGISTRY_ID = keccak256( - abi.encodePacked("DowntimeSlasher") - ); - bytes32 internal constant DOUBLE_SIGNING_SLASHER_REGISTRY_ID = keccak256( - abi.encodePacked("DoubleSigningSlasher") - ); - bytes32 internal constant ELECTION_REGISTRY_ID = keccak256(abi.encodePacked("Election")); - bytes32 internal constant EXCHANGE_REGISTRY_ID = keccak256(abi.encodePacked("Exchange")); - bytes32 internal constant EXCHANGE_EURO_REGISTRY_ID = keccak256(abi.encodePacked("ExchangeEUR")); - bytes32 internal constant EXCHANGE_REAL_REGISTRY_ID = keccak256(abi.encodePacked("ExchangeBRL")); - - bytes32 internal constant FEE_CURRENCY_WHITELIST_REGISTRY_ID = keccak256( - abi.encodePacked("FeeCurrencyWhitelist") - ); - bytes32 internal constant FEDERATED_ATTESTATIONS_REGISTRY_ID = keccak256( - abi.encodePacked("FederatedAttestations") - ); - bytes32 internal constant FREEZER_REGISTRY_ID = keccak256(abi.encodePacked("Freezer")); - bytes32 internal constant GOLD_TOKEN_REGISTRY_ID = keccak256(abi.encodePacked("GoldToken")); - bytes32 internal constant GOVERNANCE_REGISTRY_ID = keccak256(abi.encodePacked("Governance")); - bytes32 internal constant GOVERNANCE_SLASHER_REGISTRY_ID = keccak256( - abi.encodePacked("GovernanceSlasher") - ); - bytes32 internal constant LOCKED_GOLD_REGISTRY_ID = keccak256(abi.encodePacked("LockedGold")); - bytes32 internal constant RESERVE_REGISTRY_ID = keccak256(abi.encodePacked("Reserve")); - bytes32 internal constant RANDOM_REGISTRY_ID = keccak256(abi.encodePacked("Random")); - bytes32 internal constant SORTED_ORACLES_REGISTRY_ID = keccak256( - abi.encodePacked("SortedOracles") - ); - bytes32 internal constant STABLE_TOKEN_REGISTRY_ID = keccak256(abi.encodePacked("StableToken")); - bytes32 internal constant STABLE_EURO_TOKEN_REGISTRY_ID = keccak256( - abi.encodePacked("StableTokenEUR") - ); - bytes32 internal constant STABLE_REAL_TOKEN_REGISTRY_ID = keccak256( - abi.encodePacked("StableTokenBRL") - ); - bytes32 internal constant VALIDATORS_REGISTRY_ID = keccak256(abi.encodePacked("Validators")); - - modifier onlyRegisteredContract(bytes32 identifierHash) { - require( - registryContract.getAddressForOrDie(identifierHash) == msg.sender, - "only registered contract" - ); - _; - } - - modifier onlyRegisteredContracts(bytes32[] memory identifierHashes) { - require(registryContract.isOneOf(identifierHashes, msg.sender), "only registered contracts"); - _; - } - - function getAccounts() internal view returns (IAccounts) { - return IAccounts(registryContract.getAddressForOrDie(ACCOUNTS_REGISTRY_ID)); - } - - function getAttestations() internal view returns (IAttestations) { - return IAttestations(registryContract.getAddressForOrDie(ATTESTATIONS_REGISTRY_ID)); - } - - function getElection() internal view returns (IElection) { - return IElection(registryContract.getAddressForOrDie(ELECTION_REGISTRY_ID)); - } - - function getExchange() internal view returns (IExchange) { - return IExchange(registryContract.getAddressForOrDie(EXCHANGE_REGISTRY_ID)); - } - - function getExchangeDollar() internal view returns (IExchange) { - return getExchange(); - } - - function getExchangeEuro() internal view returns (IExchange) { - return IExchange(registryContract.getAddressForOrDie(EXCHANGE_EURO_REGISTRY_ID)); - } - - function getExchangeREAL() internal view returns (IExchange) { - return IExchange(registryContract.getAddressForOrDie(EXCHANGE_REAL_REGISTRY_ID)); - } - - function getFeeCurrencyWhitelistRegistry() internal view returns (IFeeCurrencyWhitelist) { - return - IFeeCurrencyWhitelist( - registryContract.getAddressForOrDie(FEE_CURRENCY_WHITELIST_REGISTRY_ID) - ); - } - - function getFederatedAttestations() internal view returns (IFederatedAttestations) { - return - IFederatedAttestations( - registryContract.getAddressForOrDie(FEDERATED_ATTESTATIONS_REGISTRY_ID) - ); - } - - function getFreezer() internal view returns (IFreezer) { - return IFreezer(registryContract.getAddressForOrDie(FREEZER_REGISTRY_ID)); - } - - function getGoldToken() internal view returns (IERC20) { - return IERC20(registryContract.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID)); - } - - function getGovernance() internal view returns (IGovernance) { - return IGovernance(registryContract.getAddressForOrDie(GOVERNANCE_REGISTRY_ID)); - } - - function getLockedGold() internal view returns (ILockedGold) { - return ILockedGold(registryContract.getAddressForOrDie(LOCKED_GOLD_REGISTRY_ID)); - } - - function getRandom() internal view returns (IRandom) { - return IRandom(registryContract.getAddressForOrDie(RANDOM_REGISTRY_ID)); - } - - function getReserve() internal view returns (IReserve) { - return IReserve(registryContract.getAddressForOrDie(RESERVE_REGISTRY_ID)); - } - - function getSortedOracles() internal view returns (ISortedOracles) { - return ISortedOracles(registryContract.getAddressForOrDie(SORTED_ORACLES_REGISTRY_ID)); - } - - function getStableToken() internal view returns (IStableToken) { - return IStableToken(registryContract.getAddressForOrDie(STABLE_TOKEN_REGISTRY_ID)); - } - - function getStableDollarToken() internal view returns (IStableToken) { - return getStableToken(); - } - - function getStableEuroToken() internal view returns (IStableToken) { - return IStableToken(registryContract.getAddressForOrDie(STABLE_EURO_TOKEN_REGISTRY_ID)); - } - - function getStableRealToken() internal view returns (IStableToken) { - return IStableToken(registryContract.getAddressForOrDie(STABLE_REAL_TOKEN_REGISTRY_ID)); - } - - function getValidators() internal view returns (IValidators) { - return IValidators(registryContract.getAddressForOrDie(VALIDATORS_REGISTRY_ID)); - } -} diff --git a/packages/protocol/contracts/common/UsingRegistryV2BackwardsCompatible.sol b/packages/protocol/contracts/common/UsingRegistryV2BackwardsCompatible.sol deleted file mode 100644 index 2ad711e43..000000000 --- a/packages/protocol/contracts/common/UsingRegistryV2BackwardsCompatible.sol +++ /dev/null @@ -1,10 +0,0 @@ -pragma solidity ^0.5.13; - -import "./UsingRegistryV2.sol"; - -contract UsingRegistryV2BackwardsCompatible is UsingRegistryV2 { - // Placeholder for registry storage var in UsingRegistry and cannot be renamed - // without breaking release tooling. - // Use `registryContract` (in UsingRegistryV2) for the actual registry address. - IRegistry public registry; -} diff --git a/packages/protocol/contracts/common/interfaces/IAccounts.sol b/packages/protocol/contracts/common/interfaces/IAccounts.sol deleted file mode 100644 index 868ce18b6..000000000 --- a/packages/protocol/contracts/common/interfaces/IAccounts.sol +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.5.13 <0.9.0; - -interface IAccounts { - function isAccount(address) external view returns (bool); - function voteSignerToAccount(address) external view returns (address); - function validatorSignerToAccount(address) external view returns (address); - function attestationSignerToAccount(address) external view returns (address); - function signerToAccount(address) external view returns (address); - function getAttestationSigner(address) external view returns (address); - function getValidatorSigner(address) external view returns (address); - function getVoteSigner(address) external view returns (address); - function hasAuthorizedVoteSigner(address) external view returns (bool); - function hasAuthorizedValidatorSigner(address) external view returns (bool); - function hasAuthorizedAttestationSigner(address) external view returns (bool); - - function setAccountDataEncryptionKey(bytes calldata) external; - function setMetadataURL(string calldata) external; - function setName(string calldata) external; - function setWalletAddress(address, uint8, bytes32, bytes32) external; - function setAccount(string calldata, bytes calldata, address, uint8, bytes32, bytes32) external; - - function getDataEncryptionKey(address) external view returns (bytes memory); - function getWalletAddress(address) external view returns (address); - function getMetadataURL(address) external view returns (string memory); - function batchGetMetadataURL(address[] calldata) - external - view - returns (uint256[] memory, bytes memory); - function getName(address) external view returns (string memory); - - function authorizeVoteSigner(address, uint8, bytes32, bytes32) external; - function authorizeValidatorSigner(address, uint8, bytes32, bytes32) external; - function authorizeValidatorSignerWithPublicKey(address, uint8, bytes32, bytes32, bytes calldata) - external; - function authorizeValidatorSignerWithKeys( - address, - uint8, - bytes32, - bytes32, - bytes calldata, - bytes calldata, - bytes calldata - ) external; - function authorizeAttestationSigner(address, uint8, bytes32, bytes32) external; - function createAccount() external returns (bool); - - function setPaymentDelegation(address, uint256) external; - function getPaymentDelegation(address) external view returns (address, uint256); - function isSigner(address, address, bytes32) external view returns (bool); -} diff --git a/packages/protocol/contracts/common/interfaces/ICeloToken.sol b/packages/protocol/contracts/common/interfaces/ICeloToken.sol deleted file mode 100644 index 7ebfbf2af..000000000 --- a/packages/protocol/contracts/common/interfaces/ICeloToken.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.5.13 <0.9.0; - -/** - * @title This interface describes the non- ERC20 shared interface for all Celo Tokens, and - * in the absence of interface inheritance is intended as a companion to IERC20.sol. - */ -interface ICeloToken { - function transferWithComment(address, uint256, string calldata) external returns (bool); - function name() external view returns (string memory); - function symbol() external view returns (string memory); - function decimals() external view returns (uint8); - function burn(uint256 value) external returns (bool); -} diff --git a/packages/protocol/contracts/common/interfaces/ICeloVersionedContract.sol b/packages/protocol/contracts/common/interfaces/ICeloVersionedContract.sol deleted file mode 100644 index 7a52c2e64..000000000 --- a/packages/protocol/contracts/common/interfaces/ICeloVersionedContract.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.5.13 <0.9.0; - -interface ICeloVersionedContract { - /** - * @notice Returns the storage, major, minor, and patch version of the contract. - * @return Storage version of the contract. - * @return Major version of the contract. - * @return Minor version of the contract. - * @return Patch version of the contract. - */ - function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256); -} diff --git a/packages/protocol/contracts/common/interfaces/IFeeCurrencyWhitelist.sol b/packages/protocol/contracts/common/interfaces/IFeeCurrencyWhitelist.sol deleted file mode 100644 index d6d98b0d6..000000000 --- a/packages/protocol/contracts/common/interfaces/IFeeCurrencyWhitelist.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.5.13 <0.9.0; - -interface IFeeCurrencyWhitelist { - function addToken(address) external; - function getWhitelist() external view returns (address[] memory); -} diff --git a/packages/protocol/contracts/common/interfaces/IFeeHandler.sol b/packages/protocol/contracts/common/interfaces/IFeeHandler.sol deleted file mode 100644 index 08be6fbb7..000000000 --- a/packages/protocol/contracts/common/interfaces/IFeeHandler.sol +++ /dev/null @@ -1,39 +0,0 @@ -pragma solidity ^0.5.13; - -import "../FixidityLib.sol"; - -interface IFeeHandler { - // sets the portion of the fee that should be burned. - function setBurnFraction(uint256 fraction) external; - - function addToken(address tokenAddress, address handlerAddress) external; - function removeToken(address tokenAddress) external; - - function setHandler(address tokenAddress, address handlerAddress) external; - - // marks token to be handled in "handleAll()) - function activateToken(address tokenAddress) external; - function deactivateToken(address tokenAddress) external; - - function sell(address tokenAddress) external; - - // calls exchange(tokenAddress), and distribute(tokenAddress) - function handle(address tokenAddress) external; - - // main entrypoint for a burn, iterates over token and calles handle - function handleAll() external; - - // Sends the balance of token at tokenAddress to feesBeneficiary, - // according to the entry tokensToDistribute[tokenAddress] - function distribute(address tokenAddress) external; - - // burns the balance of Celo in the contract minus the entry of tokensToDistribute[CeloAddress] - function burnCelo() external; - - // calls distribute for all the nonCeloTokens - function distributeAll() external; - - // in case some funds need to be returned or moved to another contract - function transfer(address token, address recipient, uint256 value) external returns (bool); - -} diff --git a/packages/protocol/contracts/common/interfaces/IFeeHandlerSeller.sol b/packages/protocol/contracts/common/interfaces/IFeeHandlerSeller.sol deleted file mode 100644 index 1ba66ea41..000000000 --- a/packages/protocol/contracts/common/interfaces/IFeeHandlerSeller.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "../FixidityLib.sol"; - -interface IFeeHandlerSeller { - function sell( - address sellTokenAddress, - address buyTokenAddress, - uint256 amount, - uint256 minAmount - ) external returns (uint256); - // in case some funds need to be returned or moved to another contract - function transfer(address token, uint256 amount, address to) external returns (bool); -} diff --git a/packages/protocol/contracts/common/interfaces/IFreezer.sol b/packages/protocol/contracts/common/interfaces/IFreezer.sol deleted file mode 100644 index e2c369671..000000000 --- a/packages/protocol/contracts/common/interfaces/IFreezer.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.5.13 <0.9.0; - -interface IFreezer { - function isFrozen(address) external view returns (bool); -} diff --git a/packages/protocol/contracts/common/interfaces/IMetaTransactionWallet.sol b/packages/protocol/contracts/common/interfaces/IMetaTransactionWallet.sol deleted file mode 100644 index 2b47c3210..000000000 --- a/packages/protocol/contracts/common/interfaces/IMetaTransactionWallet.sol +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.5.13 <0.9.0; - -interface IMetaTransactionWallet { - function setEip712DomainSeparator() external; - function executeMetaTransaction(address, uint256, bytes calldata, uint8, bytes32, bytes32) - external - returns (bytes memory); - function executeTransaction(address, uint256, bytes calldata) external returns (bytes memory); - function executeTransactions( - address[] calldata, - uint256[] calldata, - bytes calldata, - uint256[] calldata - ) external returns (bytes memory, uint256[] memory); - - // view functions - function getMetaTransactionDigest(address, uint256, bytes calldata, uint256) - external - view - returns (bytes32); - function getMetaTransactionSigner( - address, - uint256, - bytes calldata, - uint256, - uint8, - bytes32, - bytes32 - ) external view returns (address); - - //only owner - function setSigner(address) external; -} diff --git a/packages/protocol/contracts/common/interfaces/IMetaTransactionWalletDeployer.sol b/packages/protocol/contracts/common/interfaces/IMetaTransactionWalletDeployer.sol deleted file mode 100644 index f7c111741..000000000 --- a/packages/protocol/contracts/common/interfaces/IMetaTransactionWalletDeployer.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.5.13 <0.9.0; - -interface IMetaTransactionWalletDeployer { - function deploy(address, address, bytes calldata) external; -} diff --git a/packages/protocol/contracts/common/interfaces/IRegistry.sol b/packages/protocol/contracts/common/interfaces/IRegistry.sol deleted file mode 100644 index ce3cbd34f..000000000 --- a/packages/protocol/contracts/common/interfaces/IRegistry.sol +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.5.13 <0.9.0; - -interface IRegistry { - function setAddressFor(string calldata, address) external; - function getAddressForOrDie(bytes32) external view returns (address); - function getAddressFor(bytes32) external view returns (address); - function getAddressForStringOrDie(string calldata identifier) external view returns (address); - function getAddressForString(string calldata identifier) external view returns (address); - function isOneOf(bytes32[] calldata, address) external view returns (bool); -} diff --git a/packages/protocol/contracts/common/interfaces/IStableTokenMento.sol b/packages/protocol/contracts/common/interfaces/IStableTokenMento.sol deleted file mode 100644 index 9bdd6e2b4..000000000 --- a/packages/protocol/contracts/common/interfaces/IStableTokenMento.sol +++ /dev/null @@ -1,26 +0,0 @@ -pragma solidity ^0.5.13; - -/** - * @title This interface describes the functions specific to Celo Stable Tokens, and in the - * absence of interface inheritance is intended as a companion to IERC20.sol and ICeloToken.sol. - */ -interface IStableTokenMento { - function mint(address, uint256) external returns (bool); - - function burn(uint256) external returns (bool); - - function setInflationParameters(uint256, uint256) external; - - function valueToUnits(uint256) external view returns (uint256); - - function unitsToValue(uint256) external view returns (uint256); - - function getInflationParameters() external view returns (uint256, uint256, uint256, uint256); - - // NOTE: duplicated with IERC20.sol, remove once interface inheritance is supported. - function balanceOf(address) external view returns (uint256); - - function getExchangeRegistryId() external view returns (bytes32); - - function approve(address spender, uint256 value) external returns (bool); -} diff --git a/packages/protocol/contracts/common/libraries/B12.sol b/packages/protocol/contracts/common/libraries/B12.sol deleted file mode 100644 index 3b6b80e1d..000000000 --- a/packages/protocol/contracts/common/libraries/B12.sol +++ /dev/null @@ -1,888 +0,0 @@ -pragma solidity ^0.5.13; - -// Included into celo-monorepo from -// https://github.com/prestwich/b12-sol/blob/main/contracts/B12.sol -// which is largely based on -// https://github.com/ralexstokes/deposit-verifier/blob/master/deposit_verifier.sol - -import { TypedMemView } from "./TypedMemView.sol"; - -library B12 { - using TypedMemView for bytes; - using TypedMemView for bytes29; - - // Fp is a field element with the high-order part stored in `a`. - struct Fp { - uint256 a; - uint256 b; - } - - // Base field modulus from https://eips.ethereum.org/EIPS/eip-2539#specification - uint256 constant BLS12_377_BASE_A = 0x1ae3a4617c510eac63b05c06ca1493b; - uint256 constant BLS12_377_BASE_B = 0x1a22d9f300f5138f1ef3622fba094800170b5d44300000008508c00000000001; - - // Fp2 is an extension field element with the coefficient of the - // quadratic non-residue stored in `b`, i.e. p = a + i * b - struct Fp2 { - Fp a; - Fp b; - } - - // G1Point represents a point on BLS12-377 over Fp with coordinates (X,Y); - struct G1Point { - Fp X; - Fp Y; - } - - // G2Point represents a point on BLS12-377 over Fp2 with coordinates (X,Y); - struct G2Point { - Fp2 X; - Fp2 Y; - } - - struct G1MultiExpArg { - G1Point point; - uint256 scalar; - } - - struct G2MultiExpArg { - G2Point point; - uint256 scalar; - } - - struct PairingArg { - G1Point g1; - G2Point g2; - } - - function FpEq(Fp memory a, Fp memory b) internal pure returns (bool) { - return (a.a == b.a && a.b == b.b); - } - - function fpGt(Fp memory a, Fp memory b) internal pure returns (bool) { - return (a.a > b.a || (a.a == b.a && a.b > b.b)); - } - - function Fp2Eq(Fp2 memory a, Fp2 memory b) internal pure returns (bool) { - return FpEq(a.a, b.a) && FpEq(a.b, b.b); - } - - function fp2Gt(Fp2 memory a, Fp2 memory b) internal pure returns (bool) { - if (FpEq(a.b, b.b)) return fpGt(a.a, b.a); - else return fpGt(a.b, b.b); - } - - function fpAdd2(uint256 a, uint256 b) internal pure returns (Fp memory) { - return fpAdd(Fp(0, a), Fp(0, b)); - } - - function fpAdd3(uint256 a, uint256 b, uint256 c) internal pure returns (Fp memory) { - return fpAdd(Fp(0, a), fpAdd(Fp(0, b), Fp(0, c))); - } - - function fpAdd4(uint256 a, uint256 b, uint256 c, uint256 d) internal pure returns (Fp memory) { - return fpAdd(Fp(0, a), fpAdd(Fp(0, b), fpAdd(Fp(0, c), Fp(0, d)))); - } - - function fpAdd(Fp memory a, Fp memory b) internal pure returns (Fp memory) { - uint256 bb = a.b + b.b; - uint256 aa = a.a + b.a + (bb >= a.b && bb >= b.b ? 0 : 1); - return Fp(aa, bb); - } - - function fpSub(Fp memory a, Fp memory b) internal pure returns (Fp memory) { - Fp memory x = fpAdd(a, Fp(BLS12_377_BASE_A, BLS12_377_BASE_B)); - uint256 bb = x.b - b.b; - uint256 aa = x.a - b.a - (bb <= x.b ? 0 : 1); - return Fp(aa, bb); - } - - function fpModExp(Fp memory base, uint256 exponent, Fp memory modulus) - internal - view - returns (Fp memory) - { - uint256 base1 = base.a; - uint256 base2 = base.b; - uint256 modulus1 = modulus.a; - uint256 modulus2 = modulus.b; - bytes memory arg = new bytes(3 * 32 + 32 + 64 + 64); - bytes memory ret = new bytes(64); - uint256 result1; - uint256 result2; - assembly { - // length of base, exponent, modulus - mstore(add(arg, 0x20), 0x40) - mstore(add(arg, 0x40), 0x20) - mstore(add(arg, 0x60), 0x40) - - // assign base, exponent, modulus - mstore(add(arg, 0x80), base1) - mstore(add(arg, 0xa0), base2) - mstore(add(arg, 0xc0), exponent) - mstore(add(arg, 0xe0), modulus1) - mstore(add(arg, 0x100), modulus2) - - // call the precompiled contract BigModExp (0x05) - let success := staticcall(gas, 0x05, add(arg, 0x20), 0x100, add(ret, 0x20), 0x40) - switch success - case 0 { - revert(0x0, 0x0) - } - default { - result1 := mload(add(0x20, ret)) - result2 := mload(add(0x40, ret)) - } - } - return Fp(result1, result2); - } - - function fpModExp2(Fp memory base, uint256 idx, uint256 exponent, Fp memory modulus) - internal - view - returns (Fp memory) - { - uint256 base1 = base.a; - uint256 base2 = base.b; - uint256 modulus1 = modulus.a; - uint256 modulus2 = modulus.b; - bytes memory arg = new bytes(3 * 32 + 62 + 64 + 32 + idx); - bytes memory ret = new bytes(64); - uint256 result1; - uint256 result2; - assembly { - // length of base, exponent, modulus - mstore(add(arg, 0x20), add(0x40, idx)) - mstore(add(arg, 0x40), 0x20) - mstore(add(arg, 0x60), 0x40) - - // assign base, exponent, modulus - mstore(add(arg, 0x80), base1) - mstore(add(arg, 0xa0), base2) - mstore(add(arg, add(idx, 0xc0)), exponent) - mstore(add(arg, add(idx, 0xe0)), modulus1) - mstore(add(arg, add(idx, 0x100)), modulus2) - - // call the precompiled contract BigModExp (0x05) - let success := staticcall(gas, 0x05, add(arg, 0x20), add(idx, 0x100), add(ret, 0x20), 0x40) - switch success - case 0 { - revert(0x0, 0x0) - } - default { - result1 := mload(add(0x20, ret)) - result2 := mload(add(0x40, ret)) - } - } - return Fp(result1, result2); - } - - function fpMul(Fp memory a, Fp memory b) internal view returns (Fp memory) { - uint256 a1 = uint128(a.b); - uint256 a2 = uint128(a.b >> 128); - uint256 a3 = uint128(a.a); - uint256 a4 = uint128(a.a >> 128); - uint256 b1 = uint128(b.b); - uint256 b2 = uint128(b.b >> 128); - uint256 b3 = uint128(b.a); - uint256 b4 = uint128(b.a >> 128); - Fp memory res = fpNormal2(Fp(0, a1 * b1), 0); - res = fpAdd(res, fpNormal2(fpAdd2(a1 * b2, a2 * b1), 16)); - res = fpAdd(res, fpNormal2(fpAdd3(a1 * b3, a2 * b2, a3 * b1), 32)); - res = fpAdd(res, fpNormal2(fpAdd4(a1 * b4, a2 * b3, a3 * b2, a4 * b1), 48)); - res = fpAdd(res, fpNormal2(fpAdd3(a2 * b4, a3 * b3, a4 * b2), 64)); - res = fpAdd(res, fpNormal2(fpAdd2(a3 * b4, a4 * b3), 96)); - res = fpAdd(res, fpNormal2(Fp(0, a4 * b4), 128)); - return fpNormal(res); - } - - function fp2Normal(Fp2 memory a) internal view returns (Fp2 memory) { - return Fp2(fpNormal(a.a), fpNormal(a.b)); - } - - function fp2Add(Fp2 memory a, Fp2 memory b) internal pure returns (Fp2 memory) { - return Fp2(fpAdd(a.a, b.a), fpAdd(a.b, b.b)); - } - - function fp2Mul(Fp2 memory a, Fp2 memory b) internal view returns (Fp2 memory) { - Fp memory non_residue = B12.Fp( - 0x01ae3a4617c510eac63b05c06ca1493b, - 0x1a22d9f300f5138f1ef3622fba094800170b5d44300000008508bffffffffffc - ); - - Fp memory v0 = fpMul(a.a, b.a); - Fp memory v1 = fpMul(a.b, b.b); - - Fp memory res1 = fpAdd(a.b, a.a); - res1 = fpMul(res1, fpAdd(b.a, b.b)); - res1 = fpSub(res1, v0); - res1 = fpSub(res1, v1); - Fp memory res0 = fpAdd(v0, fpMul(v1, non_residue)); - return Fp2(res0, res1); - } - - function fpNormal2(Fp memory a, uint256 idx) internal view returns (Fp memory) { - return fpModExp2(a, idx, 1, Fp(BLS12_377_BASE_A, BLS12_377_BASE_B)); - } - - function fpNormal(Fp memory a) internal view returns (Fp memory) { - return fpModExp(a, 1, Fp(BLS12_377_BASE_A, BLS12_377_BASE_B)); - } - - function mapToG2(Fp2 memory x, Fp2 memory hint1, Fp2 memory hint2, bool greatest) - internal - view - returns (G2Point memory) - { - Fp2 memory one = Fp2(Fp(0, 1), Fp(0, 0)); - Fp2 memory res = fp2Add(fp2Mul(x, fp2Mul(x, x)), one); - Fp2 memory sqhint1 = fp2Mul(hint1, hint1); - Fp2 memory sqhint2 = fp2Mul(hint2, hint2); - require(Fp2Eq(sqhint1, res), "y1 not sqrt"); - require(Fp2Eq(sqhint2, res), "y2 not sqrt"); - require(fp2Gt(hint1, hint2), "y1 not greatest"); - G2Point memory p = G2Point(x, greatest ? hint1 : hint2); - return p; - } - - function mapToG1(Fp memory x, Fp memory hint1, Fp memory hint2, bool greatest) - internal - view - returns (G1Point memory) - { - Fp memory one = Fp(0, 1); - Fp memory res = fpAdd(fpModExp(x, 3, Fp(BLS12_377_BASE_A, BLS12_377_BASE_B)), one); - Fp memory sqhint1 = fpModExp(hint1, 2, Fp(BLS12_377_BASE_A, BLS12_377_BASE_B)); - Fp memory sqhint2 = fpModExp(hint2, 2, Fp(BLS12_377_BASE_A, BLS12_377_BASE_B)); - require(FpEq(sqhint1, res), "y1 not sqrt"); - require(FpEq(sqhint2, res), "y2 not sqrt"); - require(fpGt(hint1, hint2), "y1 not greatest"); - return G1Point(x, greatest ? hint1 : hint2); - } - - function parsePointGen(bytes memory h, uint256 offset) - internal - pure - returns (uint256, uint256, uint256) - { - uint256 a = 0; - uint256 b = 0; - for (uint256 i = 0; i < 32; i++) { - uint256 byt = uint256(uint8(h[offset + i])); - b = b + (byt << (i * 8)); - } - for (uint256 i = 0; i < 15; i++) { - uint256 byt = uint256(uint8(h[offset + i + 32])); - a = a + (byt << (i * 8)); - } - return (a, b, uint256(uint8(h[offset + 47]))); - } - - function parsePoint(bytes memory h, uint256 offset) internal pure returns (Fp memory, bool) { - (uint256 a, uint256 b, uint256 byt) = parsePointGen(h, offset); - a = a + ((byt & 0x7f) << (15 * 8)); - return (Fp(a, b), byt & 0xa0 != 0); - } - - function parseSimplePoint(bytes memory h, uint256 offset) internal pure returns (Fp memory) { - Fp memory res = Fp(0, 0); - parseSimplePoint(h, offset, res); - return res; - } - - function parseSimplePoint(bytes memory h, uint256 offset, Fp memory p) internal pure { - uint256 a; - uint256 b; - assembly { - a := mload(add(0x20, add(h, offset))) - b := mload(add(0x40, add(h, offset))) - } - p.a = a; - p.b = b; - } - - function parsePoint(bytes memory h) internal pure returns (Fp memory, bool) { - return parsePoint(h, 0); - } - - function parseRandomPoint(bytes memory h) internal pure returns (Fp memory, bool) { - (uint256 a, uint256 b, uint256 byt) = parsePointGen(h, 0); - a = a + ((byt & 0x01) << (15 * 8)); - return (Fp(a, b), byt & 0x02 != 0); - } - - function readFp2(bytes memory h, uint256 offset) internal pure returns (Fp2 memory) { - Fp memory a = parseSimplePoint(h, offset); - Fp memory b = parseSimplePoint(h, 64 + offset); - return Fp2(a, b); - } - - function readFp2(bytes memory h, uint256 offset, Fp2 memory p) internal pure { - parseSimplePoint(h, offset, p.a); - parseSimplePoint(h, 64 + offset, p.b); - } - - function readG2(bytes memory h, uint256 offset) internal pure returns (G2Point memory) { - Fp2 memory a = readFp2(h, offset); - Fp2 memory b = readFp2(h, 128 + offset); - return G2Point(a, b); - } - - function readG2(bytes memory h, uint256 offset, G2Point memory p) internal pure { - readFp2(h, offset, p.X); - readFp2(h, 128 + offset, p.Y); - } - - function g1Eq(G1Point memory a, G1Point memory b) internal pure returns (bool) { - return FpEq(a.X, b.X) && FpEq(a.Y, b.Y); - } - - function g1Eq(G2Point memory a, G2Point memory b) internal pure returns (bool) { - return (Fp2Eq(a.X, b.X) && Fp2Eq(a.Y, b.Y)); - } - - function parseFp(bytes memory input, uint256 offset) internal pure returns (Fp memory ret) { - bytes29 ref = input.ref(0).postfix(input.length - offset, 0); - - ret.a = ref.indexUint(0, 32); - ret.b = ref.indexUint(32, 32); - } - - function parseFp2(bytes memory input, uint256 offset) internal pure returns (Fp2 memory ret) { - bytes29 ref = input.ref(0).postfix(input.length - offset, 0); - - ret.a.a = ref.indexUint(0, 32); - ret.a.b = ref.indexUint(32, 32); - ret.b.a = ref.indexUint(64, 32); - ret.b.b = ref.indexUint(96, 32); - } - - function parseCompactFp(bytes memory input, uint256 offset) - internal - pure - returns (Fp memory ret) - { - bytes29 ref = input.ref(0).postfix(input.length - offset, 0); - - ret.a = ref.indexUint(0, 16); - ret.b = ref.indexUint(16, 32); - } - - function parseCompactFp2(bytes memory input, uint256 offset) - internal - pure - returns (Fp2 memory ret) - { - bytes29 ref = input.ref(0).postfix(input.length - offset, 0); - - ret.a.a = ref.indexUint(48, 16); - ret.a.b = ref.indexUint(64, 32); - ret.b.a = ref.indexUint(0, 16); - ret.b.b = ref.indexUint(16, 32); - } - - function parseG1(bytes memory input, uint256 offset) internal pure returns (G1Point memory ret) { - // unchecked sub is safe due to view validity checks - bytes29 ref = input.ref(0).postfix(input.length - offset, 0); - - ret.X.a = ref.indexUint(0, 32); - ret.X.b = ref.indexUint(32, 32); - ret.Y.a = ref.indexUint(64, 32); - ret.Y.b = ref.indexUint(96, 32); - } - - function parseG2(bytes memory input, uint256 offset) internal pure returns (G2Point memory ret) { - // unchecked sub is safe due to view validity checks - bytes29 ref = input.ref(0).postfix(input.length - offset, 0); - - ret.X.a.a = ref.indexUint(0, 32); - ret.X.a.b = ref.indexUint(32, 32); - ret.X.b.a = ref.indexUint(64, 32); - ret.X.b.b = ref.indexUint(96, 32); - ret.Y.a.a = ref.indexUint(128, 32); - ret.Y.a.b = ref.indexUint(160, 32); - ret.Y.b.a = ref.indexUint(192, 32); - ret.Y.b.b = ref.indexUint(224, 32); - } - - function serializeFp(Fp memory p) internal pure returns (bytes memory) { - return abi.encodePacked(p.a, p.b); - } - - function serializeFp2(Fp2 memory p) internal pure returns (bytes memory) { - return abi.encodePacked(p.a.a, p.a.b, p.b.a, p.b.b); - } - - function serializeG1(G1Point memory p) internal pure returns (bytes memory) { - return abi.encodePacked(p.X.a, p.X.b, p.Y.a, p.Y.b); - } - - function serializeG2(G2Point memory p) internal pure returns (bytes memory) { - return abi.encodePacked(p.X.a.a, p.X.a.b, p.X.b.a, p.X.b.b, p.Y.a.a, p.Y.a.b, p.Y.b.a, p.Y.b.b); - } - - function g1Add(G1Point memory a, G1Point memory b, uint8 precompile, uint256 gasEstimate) - internal - view - returns (G1Point memory c) - { - uint256[8] memory input; - input[0] = a.X.a; - input[1] = a.X.b; - input[2] = a.Y.a; - input[3] = a.Y.b; - - input[4] = b.X.a; - input[5] = b.X.b; - input[6] = b.Y.a; - input[7] = b.Y.b; - - bool success; - assembly { - success := staticcall(gasEstimate, precompile, input, 256, input, 128) - // deallocate the input, leaving dirty memory - mstore(0x40, input) - } - - require(success, "g1 add precompile failed"); - c.X.a = input[0]; - c.X.b = input[1]; - c.Y.a = input[2]; - c.Y.b = input[3]; - } - - // Overwrites A - function g1Mul(G1Point memory a, uint256 scalar, uint8 precompile, uint256 gasEstimate) - internal - view - returns (G1Point memory c) - { - uint256[5] memory input; - input[0] = a.X.a; - input[1] = a.X.b; - input[2] = a.Y.a; - input[3] = a.Y.b; - - input[4] = scalar; - - bool success; - assembly { - success := staticcall( - gasEstimate, - precompile, - input, - 160, - input, // reuse the memory to avoid growing - 128 - ) - // deallocate the input, leaving dirty memory - mstore(0x40, input) - } - require(success, "g1 mul precompile failed"); - c.X.a = input[0]; - c.X.b = input[1]; - c.Y.a = input[2]; - c.Y.b = input[3]; - } - - function g1MultiExp(G1MultiExpArg[] memory argVec, uint8 precompile, uint256 gasEstimate) - internal - view - returns (G1Point memory c) - { - uint256[] memory input = new uint256[](argVec.length * 5); - // hate this - for (uint256 i = 0; i < argVec.length; i++) { - input[i * 5 + 0] = argVec[i].point.X.a; - input[i * 5 + 1] = argVec[i].point.X.b; - input[i * 5 + 2] = argVec[i].point.Y.a; - input[i * 5 + 3] = argVec[i].point.Y.b; - input[i * 5 + 4] = argVec[i].scalar; - } - - bool success; - assembly { - success := staticcall( - gasEstimate, - precompile, - add(input, 0x20), - mul(mload(input), 0x20), - add(input, 0x20), - 128 - ) - // deallocate the input, leaving dirty memory - mstore(0x40, input) - } - require(success, "g1 multiExp precompile failed"); - c.X.a = input[0]; - c.X.b = input[1]; - c.Y.a = input[2]; - c.Y.b = input[3]; - } - - function g2Add(G2Point memory a, G2Point memory b, uint8 precompile, uint256 gasEstimate) - internal - view - returns (G2Point memory c) - { - uint256[16] memory input; - input[0] = a.X.a.a; - input[1] = a.X.a.b; - input[2] = a.X.b.a; - input[3] = a.X.b.b; - - input[4] = a.Y.a.a; - input[5] = a.Y.a.b; - input[6] = a.Y.b.a; - input[7] = a.Y.b.b; - - input[8] = b.X.a.a; - input[9] = b.X.a.b; - input[10] = b.X.b.a; - input[11] = b.X.b.b; - - input[12] = b.Y.a.a; - input[13] = b.Y.a.b; - input[14] = b.Y.b.a; - input[15] = b.Y.b.b; - - bool success; - assembly { - success := staticcall( - gasEstimate, - precompile, - input, - 512, - input, // reuse the memory to avoid growing - 256 - ) - // deallocate the input, leaving dirty memory - mstore(0x40, input) - } - require(success, "g2 add precompile failed"); - c.X.a.a = input[0]; - c.X.a.b = input[1]; - c.X.b.a = input[2]; - c.X.b.b = input[3]; - - c.Y.a.a = input[4]; - c.Y.a.b = input[5]; - c.Y.b.a = input[6]; - c.Y.b.b = input[7]; - } - - // Overwrites A - function g2Mul(G2Point memory a, uint256 scalar, uint8 precompile, uint256 gasEstimate) - internal - view - { - uint256[9] memory input; - - input[0] = a.X.a.a; - input[1] = a.X.a.b; - input[2] = a.X.b.a; - input[3] = a.X.b.b; - - input[4] = a.Y.a.a; - input[5] = a.Y.a.b; - input[6] = a.Y.b.a; - input[7] = a.Y.b.b; - - input[8] = scalar; - - bool success; - assembly { - success := staticcall( - gasEstimate, - precompile, - input, - 288, - input, // reuse the memory to avoid growing - 256 - ) - // deallocate the input, leaving dirty memory - mstore(0x40, input) - } - require(success, "g2 mul precompile failed"); - a.X.a.a = input[0]; - a.X.a.b = input[1]; - a.X.b.a = input[2]; - a.X.b.b = input[3]; - a.Y.a.a = input[4]; - a.Y.a.b = input[5]; - a.Y.b.a = input[6]; - a.Y.b.b = input[7]; - } - - function g2MultiExp(G2MultiExpArg[] memory argVec, uint8 precompile, uint256 gasEstimate) - internal - view - returns (G2Point memory c) - { - uint256[] memory input = new uint256[](argVec.length * 9); - // hate this - for (uint256 i = 0; i < input.length / 9; i += 1) { - uint256 idx = i * 9; - input[idx + 0] = argVec[i].point.X.a.a; - input[idx + 1] = argVec[i].point.X.a.b; - input[idx + 2] = argVec[i].point.X.b.a; - input[idx + 3] = argVec[i].point.X.b.b; - input[idx + 4] = argVec[i].point.Y.a.a; - input[idx + 5] = argVec[i].point.Y.a.b; - input[idx + 6] = argVec[i].point.Y.b.a; - input[idx + 7] = argVec[i].point.Y.b.b; - input[idx + 8] = argVec[i].scalar; - } - - bool success; - assembly { - success := staticcall( - gasEstimate, - precompile, - add(input, 0x20), - mul(mload(input), 0x20), // 288 bytes per arg - add(input, 0x20), // write directly to the already allocated result - 256 - ) - // deallocate the input, leaving dirty memory - mstore(0x40, input) - } - require(success, "g2 multiExp precompile failed"); - c.X.a.a = input[0]; - c.X.a.b = input[1]; - c.X.b.a = input[2]; - c.X.b.b = input[3]; - c.Y.a.a = input[4]; - c.Y.a.b = input[5]; - c.Y.b.a = input[6]; - c.Y.b.b = input[7]; - } - - function pairing(PairingArg[] memory argVec, uint8 precompile, uint256 gasEstimate) - internal - view - returns (bool result) - { - uint256 len = argVec.length; - uint256[] memory input = new uint256[](len * 12); - - for (uint256 i = 0; i < len; i++) { - uint256 idx = i * 12; - input[idx + 0] = argVec[i].g1.X.a; - input[idx + 1] = argVec[i].g1.X.b; - input[idx + 2] = argVec[i].g1.Y.a; - input[idx + 3] = argVec[i].g1.Y.b; - input[idx + 4] = argVec[i].g2.X.a.a; - input[idx + 5] = argVec[i].g2.X.a.b; - input[idx + 6] = argVec[i].g2.X.b.a; - input[idx + 7] = argVec[i].g2.X.b.b; - input[idx + 8] = argVec[i].g2.Y.a.a; - input[idx + 9] = argVec[i].g2.Y.a.b; - input[idx + 10] = argVec[i].g2.Y.b.a; - input[idx + 11] = argVec[i].g2.Y.b.b; - } - - bool success; - assembly { - success := staticcall( - gasEstimate, - precompile, - add(input, 0x20), // the body of the array - mul(384, len), // 384 bytes per arg - mload(0x40), // write to earliest freemem - 32 - ) - result := mload(mload(0x40)) // load what we just wrote - // deallocate the input, leaving dirty memory - mstore(0x40, input) - } - require(success, "pairing precompile failed"); - } -} - -library B12_381Lib { - using B12 for B12.G1Point; - using B12 for B12.G2Point; - - uint8 constant G1_ADD = 0xF2; - uint8 constant G1_MUL = 0xF1; - uint8 constant G1_MULTI_EXP = 0xF0; - uint8 constant G2_ADD = 0xEF; - uint8 constant G2_MUL = 0xEE; - uint8 constant G2_MULTI_EXP = 0xED; - uint8 constant PAIRING = 0xEC; - uint8 constant MAP_TO_G1 = 0xEB; - uint8 constant MAP_TO_G2 = 0xEA; - - function negativeP1() internal pure returns (B12.G1Point memory p) { - p.X.a = 31827880280837800241567138048534752271; - p.X.b = 88385725958748408079899006800036250932223001591707578097800747617502997169851; - p.Y.a = 22997279242622214937712647648895181298; - p.Y.b = 46816884707101390882112958134453447585552332943769894357249934112654335001290; - } - - function mapToG1(B12.Fp memory a) internal view returns (B12.G1Point memory b) { - uint256[2] memory input; - input[0] = a.a; - input[1] = a.b; - - bool success; - uint8 ADDR = MAP_TO_G1; - assembly { - success := staticcall( - 20000, - ADDR, - input, // the body of the array - 64, - b, // write directly to pre-allocated result - 128 - ) - // deallocate the input - mstore(add(input, 0), 0) - mstore(add(input, 0x20), 0) - mstore(0x40, input) - } - } - - function mapToG2(B12.Fp2 memory a) internal view returns (B12.G2Point memory b) { - uint256[4] memory input; - input[0] = a.a.a; - input[1] = a.a.b; - input[2] = a.b.a; - input[3] = a.b.b; - - bool success; - uint8 ADDR = MAP_TO_G2; - assembly { - success := staticcall( - 120000, - ADDR, - input, // the body of the array - 128, - b, // write directly to pre-allocated result - 256 - ) - // deallocate the input - mstore(add(input, 0), 0) - mstore(add(input, 0x20), 0) - mstore(add(input, 0x40), 0) - mstore(add(input, 0x60), 0) - mstore(0x40, input) - } - } - - function g1Add(B12.G1Point memory a, B12.G1Point memory b) - internal - view - returns (B12.G1Point memory c) - { - return a.g1Add(b, G1_ADD, 15000); - } - - function g1Mul(B12.G1Point memory a, uint256 scalar) - internal - view - returns (B12.G1Point memory c) - { - return a.g1Mul(scalar, G1_MUL, 50000); - } - - function g1MultiExp(B12.G1MultiExpArg[] memory argVec) - internal - view - returns (B12.G1Point memory c) - { - uint256 roughCost = (argVec.length * 12000 * 1200) / 1000; - return B12.g1MultiExp(argVec, G1_MULTI_EXP, roughCost); - } - - function g2Add(B12.G2Point memory a, B12.G2Point memory b) - internal - view - returns (B12.G2Point memory c) - { - return a.g2Add(b, G2_ADD, 20000); - } - - function g2Mul(B12.G2Point memory a, uint256 scalar) internal view { - return a.g2Mul(scalar, G2_MUL, 60000); - } - - function g2MultiExp(B12.G2MultiExpArg[] memory argVec) - internal - view - returns (B12.G2Point memory c) - { - uint256 roughCost = (argVec.length * 55000 * 1200) / 1000; - return B12.g2MultiExp(argVec, G2_MULTI_EXP, roughCost); - } - - function pairing(B12.PairingArg[] memory argVec) internal view returns (bool result) { - uint256 roughCost = (23000 * argVec.length) + 115000; - return B12.pairing(argVec, PAIRING, roughCost); - } -} - -library B12_377Lib { - using B12 for B12.G1Point; - using B12 for B12.G2Point; - - uint8 constant G1_ADD = 0xE9; - uint8 constant G1_MUL = 0xE8; - uint8 constant G1_MULTI_EXP = 0xE7; - uint8 constant G2_ADD = 0xE6; - uint8 constant G2_MUL = 0xE5; - uint8 constant G2_MULTI_EXP = 0xE4; - uint8 constant PAIRING = 0xE3; - - function g1Add(B12.G1Point memory a, B12.G1Point memory b) - internal - view - returns (B12.G1Point memory c) - { - return a.g1Add(b, G1_ADD, 15000); - } - - function g1Mul(B12.G1Point memory a, uint256 scalar) - internal - view - returns (B12.G1Point memory c) - { - return a.g1Mul(scalar, G1_MUL, 50000); - } - - function g1MultiExp(B12.G1MultiExpArg[] memory argVec) - internal - view - returns (B12.G1Point memory c) - { - uint256 roughCost = (argVec.length * 12000 * 1200) / 1000; - return B12.g1MultiExp(argVec, G1_MULTI_EXP, roughCost); - } - - function g2Add(B12.G2Point memory a, B12.G2Point memory b) - internal - view - returns (B12.G2Point memory c) - { - return a.g2Add(b, G2_ADD, 20000); - } - - function g2Mul(B12.G2Point memory a, uint256 scalar) internal view { - return a.g2Mul(scalar, G2_MUL, 60000); - } - - function g2MultiExp(B12.G2MultiExpArg[] memory argVec) - internal - view - returns (B12.G2Point memory c) - { - uint256 roughCost = (argVec.length * 55000 * 1200) / 1000; - return B12.g2MultiExp(argVec, G2_MULTI_EXP, roughCost); - } - - function pairing(B12.PairingArg[] memory argVec) internal view returns (bool result) { - uint256 roughCost = (55000 * argVec.length) + 65000; - return B12.pairing(argVec, PAIRING, roughCost); - } -} diff --git a/packages/protocol/contracts/common/libraries/CIP20Lib.sol b/packages/protocol/contracts/common/libraries/CIP20Lib.sol deleted file mode 100644 index 4ea852205..000000000 --- a/packages/protocol/contracts/common/libraries/CIP20Lib.sol +++ /dev/null @@ -1,140 +0,0 @@ -// From https://github.com/prestwich/cip20-sol -pragma solidity ^0.5.13; - -library CIP20Lib { - uint8 private constant CIP20_ADDRESS = 0xE2; - - uint8 private constant SHA3_256_SELECTOR = 0x00; - uint8 private constant SHA3_512_SELECTOR = 0x01; - uint8 private constant KECCAK_512_SELECTOR = 0x02; - uint8 private constant SHA2_512_SELECTOR = 0x03; - uint8 private constant BLAKE2S_SELECTOR = 0x10; - - // BLAKE2S_DEFAULT_CONFIG = createBlake2sConfig(32, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0) - bytes32 private constant BLAKE2S_DEFAULT_CONFIG = 0x2000010100000000000000000000000000000000000000000000000000000000; - - // Accepts a fully formed input blob. This should include any config - // options and the preimage, but not the selector. - function executeCIP20(bytes memory input, uint8 selector, uint256 output_len) - internal - view - returns (bytes memory) - { - uint8 addr = CIP20_ADDRESS; - bytes memory output = new bytes(output_len); - - // To avoid copying the input array (an unbounded cost) we store its - // length on the stack and then replace the length prefix for its - // in-memory representation with the selector. We then replace the - // length in memory after the precompile executes with it. - uint256 len = input.length; - - bool success; - assembly { - mstore(input, selector) // selector - - success := staticcall( - sub(gas, 2000), - addr, - add(input, 0x1F), // location is shifted 1 byte for selector - add(len, 0x01), // length w/ selector - add(output, 0x20), // location - mload(output) // length - ) - - // Restore the input array length prefix - mstore(input, len) - } - - require(success, "CIP-20 hashing failed"); - return output; - } - - function sha3_256(bytes memory input) internal view returns (bytes memory) { - return executeCIP20(input, SHA3_256_SELECTOR, 32); - } - - function sha3_512(bytes memory input) internal view returns (bytes memory) { - return executeCIP20(input, SHA3_512_SELECTOR, 64); - } - - function keccak512(bytes memory input) internal view returns (bytes memory) { - return executeCIP20(input, KECCAK_512_SELECTOR, 64); - } - - function sha2_512(bytes memory input) internal view returns (bytes memory) { - return executeCIP20(input, SHA2_512_SELECTOR, 64); - } - - function blake2sWithConfig(bytes32 config, bytes memory key, bytes memory preimage) - internal - view - returns (bytes memory) - { - require( - key.length == uint256(config >> (8 * 30)) & 0xff, - "CIP20Lib/blake2sWithConfig - Provided key length does not match key length in config" - ); - bytes memory configuredInput = abi.encodePacked(config, preimage); - return executeCIP20(configuredInput, BLAKE2S_SELECTOR, uint256(uint8(config[0]))); - } - - function blake2s(bytes memory preimage) internal view returns (bytes memory) { - return blake2sWithConfig(BLAKE2S_DEFAULT_CONFIG, hex"", preimage); - } - - function createBlake2sConfig( - uint8 digestSize, - uint8 keyLength, - uint8 fanout, - uint8 depth, - uint32 leafLength, - uint32 nodeOffset, - uint16 xofDigestLength, - uint8 nodeDepth, - uint8 innerLength, - bytes8 salt, - bytes8 personalize - ) internal pure returns (bytes32 config) { - require(keyLength <= 32, "CIP20Lib/createBlake2sConfig -- keyLength must be 32 or less"); - config = writeU8(config, 0, digestSize); - config = writeU8(config, 1, keyLength); - - config = writeU8(config, 2, fanout); - config = writeU8(config, 3, depth); - config = writeLEU32(config, 4, leafLength); - config = writeLEU32(config, 8, nodeOffset); - config = writeLEU16(config, 12, xofDigestLength); - config = writeU8(config, 14, nodeDepth); - config = writeU8(config, 15, innerLength); - - config |= bytes32(uint256(uint64(salt))) << (8 * 8); - config |= bytes32(uint256(uint64(personalize))) << (8 * 0); - return config; - } - - // This function relies on alignment mechanics. Explicit conversion to - // `bytes` types shorter than 32 results in left re-alignment. To avoid - // that, we convert the bytes32 to uint256 instead of converting the uint8 - // to a bytes1. - function writeU8(bytes32 b, uint8 offset, uint8 toWrite) private pure returns (bytes32) { - require(offset <= 31, "CIP20Lib/writeU8 -- out of bounds write"); - uint8 shift = 8 * (32 - 1 - offset); - bytes32 res = bytes32(uint256(b) | (uint256(toWrite) << shift)); - return res; - } - - function writeLEU32(bytes32 b, uint8 offset, uint32 toWrite) private pure returns (bytes32) { - b = writeU8(b, offset + 0, uint8(toWrite >> 0)); - b = writeU8(b, offset + 1, uint8(toWrite >> 8)); - b = writeU8(b, offset + 2, uint8(toWrite >> 16)); - b = writeU8(b, offset + 3, uint8(toWrite >> 24)); - return b; - } - - function writeLEU16(bytes32 b, uint8 offset, uint16 toWrite) private pure returns (bytes32) { - b = writeU8(b, offset + 0, uint8(toWrite >> 0)); - b = writeU8(b, offset + 1, uint8(toWrite >> 8)); - return b; - } -} diff --git a/packages/protocol/contracts/common/libraries/Heap.sol b/packages/protocol/contracts/common/libraries/Heap.sol deleted file mode 100644 index c4bafc543..000000000 --- a/packages/protocol/contracts/common/libraries/Heap.sol +++ /dev/null @@ -1,57 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "../FixidityLib.sol"; - -/** - * @title Simple heap implementation - */ -library Heap { - using FixidityLib for FixidityLib.Fraction; - using SafeMath for uint256; - - /** - * @notice Fixes the heap invariant. - * @param keys Pointers to values - * @param values Values that are compared, only the pointers are changed by this method. - * @param start Node for which the invariant might have changed. - * @param length Size of the heap. - */ - function siftDown( - uint256[] memory keys, - FixidityLib.Fraction[] memory values, - uint256 start, - uint256 length - ) internal pure { - require(keys.length == values.length, "key and value array length mismatch"); - require(start < keys.length, "heap start index out of range"); - require(length <= keys.length, "heap length out of range"); - uint256 i = start; - while (true) { - uint256 leftChild = i.mul(2).add(1); - uint256 rightChild = i.mul(2).add(2); - uint256 maxIndex = i; - if (leftChild < length && values[keys[leftChild]].gt(values[keys[maxIndex]])) { - maxIndex = leftChild; - } - if (rightChild < length && values[keys[rightChild]].gt(values[keys[maxIndex]])) { - maxIndex = rightChild; - } - if (maxIndex == i) break; - uint256 tmpKey = keys[i]; - keys[i] = keys[maxIndex]; - keys[maxIndex] = tmpKey; - i = maxIndex; - } - } - - /** - * @notice Fixes the heap invariant if top has been changed. - * @param keys Pointers to values - * @param values Values that are compared, only the pointers are changed by this method. - */ - function heapifyDown(uint256[] memory keys, FixidityLib.Fraction[] memory values) internal pure { - siftDown(keys, values, 0, keys.length); - } - -} diff --git a/packages/protocol/contracts/common/libraries/ReentrancyGuard.sol b/packages/protocol/contracts/common/libraries/ReentrancyGuard.sol deleted file mode 100644 index 34d5213d5..000000000 --- a/packages/protocol/contracts/common/libraries/ReentrancyGuard.sol +++ /dev/null @@ -1,32 +0,0 @@ -pragma solidity ^0.5.13; - -/** - * @title Helps contracts guard against reentrancy attacks. - * @author Remco Bloemen , Eenae - * @dev If you mark a function `nonReentrant`, you should also - * mark it `external`. - */ -contract ReentrancyGuard { - /// @dev counter to allow mutex lock with only one SSTORE operation - uint256 private _guardCounter; - - constructor() internal { - // The counter starts at one to prevent changing it from zero to a non-zero - // value, which is a more expensive operation. - _guardCounter = 1; - } - - /** - * @dev Prevents a contract from calling itself, directly or indirectly. - * Calling a `nonReentrant` function from another `nonReentrant` - * function is not supported. It is possible to prevent this from happening - * by making the `nonReentrant` function external, and make it call a - * `private` function that does the actual work. - */ - modifier nonReentrant() { - _guardCounter += 1; - uint256 localCounter = _guardCounter; - _; - require(localCounter == _guardCounter, "reentrant call"); - } -} diff --git a/packages/protocol/contracts/common/libraries/SafeMathMem.sol b/packages/protocol/contracts/common/libraries/SafeMathMem.sol deleted file mode 100644 index 50920d7cf..000000000 --- a/packages/protocol/contracts/common/libraries/SafeMathMem.sol +++ /dev/null @@ -1,77 +0,0 @@ -// SPDX-License-Identifier: MIT -// Original authors: https://github.com/summa-tx/memview-sol -pragma solidity >=0.5.10 <0.8.0; - -/* -The MIT License (MIT) - -Copyright (c) 2016 Smart Contract Solutions, Inc. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -/** - * @title SafeMath - * @dev Math operations with safety checks that throw on error - */ -library SafeMathMem { - /** - * @dev Multiplies two numbers, throws on overflow. - */ - function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) { - // Gas optimization: this is cheaper than asserting 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 - if (_a == 0) { - return 0; - } - - c = _a * _b; - require(c / _a == _b, "Overflow during multiplication."); - return c; - } - - /** - * @dev Integer division of two numbers, truncating the quotient. - */ - function div(uint256 _a, uint256 _b) internal pure returns (uint256) { - // assert(_b > 0); // Solidity automatically throws when dividing by 0 - // uint256 c = _a / _b; - // assert(_a == _b * c + _a % _b); // There is no case in which this doesn't hold - return _a / _b; - } - - /** - * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). - */ - function sub(uint256 _a, uint256 _b) internal pure returns (uint256) { - require(_b <= _a, "Underflow during subtraction."); - return _a - _b; - } - - /** - * @dev Adds two numbers, throws on overflow. - */ - function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) { - c = _a + _b; - require(c >= _a, "Overflow during addition."); - return c; - } -} diff --git a/packages/protocol/contracts/common/libraries/TypedMemView.sol b/packages/protocol/contracts/common/libraries/TypedMemView.sol deleted file mode 100644 index 7698e890d..000000000 --- a/packages/protocol/contracts/common/libraries/TypedMemView.sol +++ /dev/null @@ -1,829 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -// Original authors: https://github.com/summa-tx/memview-sol -pragma solidity >=0.5.10 <0.8.0; - -import { SafeMathMem } from "./SafeMathMem.sol"; - -library TypedMemView { - using SafeMathMem for uint256; - - // Why does this exist? - // the solidity `bytes memory` type has a few weaknesses. - // 1. You can't index ranges effectively - // 2. You can't slice without copying - // 3. The underlying data may represent any type - // 4. Solidity never deallocates memory, and memory costs grow - // superlinearly - - // By using a memory view instead of a `bytes memory` we get the following - // advantages: - // 1. Slices are done on the stack, by manipulating the pointer - // 2. We can index arbitrary ranges and quickly convert them to stack types - // 3. We can insert type info into the pointer, and typecheck at runtime - - // This makes `TypedMemView` a useful tool for efficient zero-copy - // algorithms. - - // Why bytes29? - // We want to avoid confusion between views, digests, and other common - // types so we chose a large and uncommonly used odd number of bytes - // - // Note that while bytes are left-aligned in a word, integers and addresses - // are right-aligned. This means when working in assembly we have to - // account for the 3 unused bytes on the righthand side - // - // First 5 bytes are a type flag. - // - ff_ffff_fffe is reserved for unknown type. - // - ff_ffff_ffff is reserved for invalid types/errors. - // next 12 are memory address - // next 12 are len - // bottom 3 bytes are empty - - // Assumptions: - // - non-modification of memory. - // - No Solidity updates - // - - wrt free mem point - // - - wrt bytes representation in memory - // - - wrt memory addressing in general - - // Usage: - // - create type constants - // - use `assertType` for runtime type assertions - // - - unfortunately we can't do this at compile time yet :( - // - recommended: implement modifiers that perform type checking - // - - e.g. - // - - `uint40 constant MY_TYPE = 3;` - // - - ` modifer onlyMyType(bytes29 myView) { myView.assertType(MY_TYPE); }` - // - instantiate a typed view from a bytearray using `ref` - // - use `index` to inspect the contents of the view - // - use `slice` to create smaller views into the same memory - // - - `slice` can increase the offset - // - - `slice can decrease the length` - // - - must specify the output type of `slice` - // - - `slice` will return a null view if you try to overrun - // - - make sure to explicitly check for this with `notNull` or `assertType` - // - use `equal` for typed comparisons. - - // The null view - bytes29 public constant NULL = hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; - // Mask a low uint96 - uint256 constant LOW_12_MASK = 0xffffffffffffffffffffffff; - // Shift constants - uint8 constant SHIFT_TO_LEN = 24; - uint8 constant SHIFT_TO_LOC = 96 + 24; - uint8 constant SHIFT_TO_TYPE = 96 + 96 + 24; - // For nibble encoding - bytes private constant NIBBLE_LOOKUP = "0123456789abcdef"; - - /** - * @notice Returns the encoded hex character that represents the lower 4 bits of the argument. - * @param _byte The byte - * @return _char The encoded hex character - */ - function nibbleHex(uint8 _byte) internal pure returns (uint8 _char) { - uint8 _nibble = _byte & 0x0f; // keep bottom 4, 0 top 4 - _char = uint8(NIBBLE_LOOKUP[_nibble]); - } - /** - * @notice Returns a uint16 containing the hex-encoded byte. - * @param _b The byte - * @return encoded - The hex-encoded byte - */ - function byteHex(uint8 _b) internal pure returns (uint16 encoded) { - encoded |= nibbleHex(_b >> 4); // top 4 bits - encoded <<= 8; - encoded |= nibbleHex(_b); // lower 4 bits - } - - /** - * @notice Encodes the uint256 to hex. `first` contains the encoded top 16 bytes. - * `second` contains the encoded lower 16 bytes. - * - * @param _b The 32 bytes as uint256 - * @return first - The top 16 bytes - * @return second - The bottom 16 bytes - */ - function encodeHex(uint256 _b) internal pure returns (uint256 first, uint256 second) { - for (uint8 i = 31; i > 15; i -= 1) { - uint8 _byte = uint8(_b >> (i * 8)); - first |= byteHex(_byte); - if (i != 16) { - first <<= 16; - } - } - - // abusing underflow here =_= - for (uint8 i = 15; i < 255; i -= 1) { - uint8 _byte = uint8(_b >> (i * 8)); - second |= byteHex(_byte); - if (i != 0) { - second <<= 16; - } - } - } - - /** - * @notice Changes the endianness of a uint256. - * @dev https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel - * @param _b The unsigned integer to reverse - * @return v - The reversed value - */ - function reverseUint256(uint256 _b) internal pure returns (uint256 v) { - v = _b; - - // swap bytes - v = - ((v >> 8) & 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) | - ((v & 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) << 8); - // swap 2-byte long pairs - v = - ((v >> 16) & 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) | - ((v & 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) << 16); - // swap 4-byte long pairs - v = - ((v >> 32) & 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) | - ((v & 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) << 32); - // swap 8-byte long pairs - v = - ((v >> 64) & 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) | - ((v & 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) << 64); - // swap 16-byte long pairs - v = (v >> 128) | (v << 128); - } - - /** - * @notice Create a mask with the highest `_len` bits set. - * @param _len The length - * @return mask - The mask - */ - function leftMask(uint8 _len) private pure returns (uint256 mask) { - // ugly. redo without assembly? - assembly { - // solium-disable-previous-line security/no-inline-assembly - mask := sar(sub(_len, 1), 0x8000000000000000000000000000000000000000000000000000000000000000) - } - } - - /** - * @notice Return the null view. - * @return bytes29 - The null view - */ - function nullView() internal pure returns (bytes29) { - return NULL; - } - - /** - * @notice Check if the view is null. - * @return bool - True if the view is null - */ - function isNull(bytes29 memView) internal pure returns (bool) { - return memView == NULL; - } - - /** - * @notice Check if the view is not null. - * @return bool - True if the view is not null - */ - function notNull(bytes29 memView) internal pure returns (bool) { - return !isNull(memView); - } - - /** - * @notice Check if the view is of a valid type and points to a valid location - * in memory. - * @dev We perform this check by examining solidity's unallocated memory - * pointer and ensuring that the view's upper bound is less than that. - * @param memView The view - * @return ret - True if the view is valid - */ - function isValid(bytes29 memView) internal pure returns (bool ret) { - if (typeOf(memView) == 0xffffffffff) { - return false; - } - uint256 _end = end(memView); - assembly { - // solhint-disable-previous-line no-inline-assembly - ret := iszero(gt(_end, mload(0x40))) - } - } - - /** - * @notice Require that a typed memory view be valid. - * @dev Returns the view for easy chaining. - * @param memView The view - * @return bytes29 - The validated view - */ - function assertValid(bytes29 memView) internal pure returns (bytes29) { - require(isValid(memView), "Validity assertion failed"); - return memView; - } - - /** - * @notice Return true if the memview is of the expected type. Otherwise false. - * @param memView The view - * @param _expected The expected type - * @return bool - True if the memview is of the expected type - */ - function isType(bytes29 memView, uint40 _expected) internal pure returns (bool) { - return typeOf(memView) == _expected; - } - - /** - * @notice Require that a typed memory view has a specific type. - * @dev Returns the view for easy chaining. - * @param memView The view - * @param _expected The expected type - * @return bytes29 - The view with validated type - */ - function assertType(bytes29 memView, uint40 _expected) internal pure returns (bytes29) { - if (!isType(memView, _expected)) { - (, uint256 g) = encodeHex(uint256(typeOf(memView))); - (, uint256 e) = encodeHex(uint256(_expected)); - string memory err = string( - abi.encodePacked("Type assertion failed. Got 0x", uint80(g), ". Expected 0x", uint80(e)) - ); - revert(err); - } - return memView; - } - - /** - * @notice Return an identical view with a different type. - * @param memView The view - * @param _newType The new type - * @return newView - The new view with the specified type - */ - function castTo(bytes29 memView, uint40 _newType) internal pure returns (bytes29 newView) { - // then | in the new type - uint256 _typeShift = SHIFT_TO_TYPE; - uint256 _typeBits = 40; - assembly { - // solium-disable-previous-line security/no-inline-assembly - // shift off the top 5 bytes - newView := or(newView, shr(_typeBits, shl(_typeBits, memView))) - newView := or(newView, shl(_typeShift, _newType)) - } - } - - /** - * @notice Unsafe raw pointer construction. This should generally not be called - * directly. Prefer `ref` wherever possible. - * @dev Unsafe raw pointer construction. This should generally not be called - * directly. Prefer `ref` wherever possible. - * @param _type The type - * @param _loc The memory address - * @param _len The length - * @return newView - The new view with the specified type, location and length - */ - function unsafeBuildUnchecked(uint256 _type, uint256 _loc, uint256 _len) - private - pure - returns (bytes29 newView) - { - uint256 _uint96Bits = 96; - uint256 _emptyBits = 24; - assembly { - // solium-disable-previous-line security/no-inline-assembly - newView := shl(_uint96Bits, or(newView, _type)) // insert type - newView := shl(_uint96Bits, or(newView, _loc)) // insert loc - newView := shl(_emptyBits, or(newView, _len)) // empty bottom 3 bytes - } - } - - /** - * @notice Instantiate a new memory view. This should generally not be called - * directly. Prefer `ref` wherever possible. - * @dev Instantiate a new memory view. This should generally not be called - * directly. Prefer `ref` wherever possible. - * @param _type The type - * @param _loc The memory address - * @param _len The length - * @return newView - The new view with the specified type, location and length - */ - function build(uint256 _type, uint256 _loc, uint256 _len) - internal - pure - returns (bytes29 newView) - { - uint256 _end = _loc.add(_len); - assembly { - // solium-disable-previous-line security/no-inline-assembly - if gt(_end, mload(0x40)) { - _end := 0 - } - } - if (_end == 0) { - return NULL; - } - newView = unsafeBuildUnchecked(_type, _loc, _len); - } - - /** - * @notice Instantiate a memory view from a byte array. - * @dev Note that due to Solidity memory representation, it is not possible to - * implement a deref, as the `bytes` type stores its len in memory. - * @param arr The byte array - * @param newType The type - * @return bytes29 - The memory view - */ - function ref(bytes memory arr, uint40 newType) internal pure returns (bytes29) { - uint256 _len = arr.length; - - uint256 _loc; - assembly { - // solium-disable-previous-line security/no-inline-assembly - _loc := add(arr, 0x20) // our view is of the data, not the struct - } - - return build(newType, _loc, _len); - } - - /** - * @notice Return the associated type information. - * @param memView The memory view - * @return _type - The type associated with the view - */ - function typeOf(bytes29 memView) internal pure returns (uint40 _type) { - uint256 _shift = SHIFT_TO_TYPE; - assembly { - // solium-disable-previous-line security/no-inline-assembly - _type := shr(_shift, memView) // shift out lower 27 bytes - } - } - - /** - * @notice Optimized type comparison. Checks that the 5-byte type flag is equal. - * @param left The first view - * @param right The second view - * @return bool - True if the 5-byte type flag is equal - */ - function sameType(bytes29 left, bytes29 right) internal pure returns (bool) { - return (left ^ right) >> SHIFT_TO_TYPE == 0; - } - - /** - * @notice Return the memory address of the underlying bytes. - * @param memView The view - * @return _loc - The memory address - */ - function loc(bytes29 memView) internal pure returns (uint96 _loc) { - uint256 _mask = LOW_12_MASK; // assembly can't use globals - uint256 _shift = SHIFT_TO_LOC; - assembly { - // solium-disable-previous-line security/no-inline-assembly - _loc := and(shr(_shift, memView), _mask) - } - } - - /** - * @notice The number of memory words this memory view occupies, rounded up. - * @param memView The view - * @return uint256 - The number of memory words - */ - function words(bytes29 memView) internal pure returns (uint256) { - return uint256(len(memView)).add(31) / 32; - } - - /** - * @notice The in-memory footprint of a fresh copy of the view. - * @param memView The view - * @return uint256 - The in-memory footprint of a fresh copy of the view. - */ - function footprint(bytes29 memView) internal pure returns (uint256) { - return words(memView) * 32; - } - - /** - * @notice The number of bytes of the view. - * @param memView The view - * @return _len - The length of the view - */ - function len(bytes29 memView) internal pure returns (uint96 _len) { - uint256 _mask = LOW_12_MASK; // assembly can't use globals - uint256 _emptyBits = 24; - assembly { - // solium-disable-previous-line security/no-inline-assembly - _len := and(shr(_emptyBits, memView), _mask) - } - } - - /** - * @notice Returns the endpoint of `memView`. - * @param memView The view - * @return uint256 - The endpoint of `memView` - */ - function end(bytes29 memView) internal pure returns (uint256) { - return loc(memView) + len(memView); - } - - /** - * @notice Safe slicing without memory modification. - * @param memView The view - * @param _index The start index - * @param _len The length - * @param newType The new type - * @return bytes29 - The new view - */ - function slice(bytes29 memView, uint256 _index, uint256 _len, uint40 newType) - internal - pure - returns (bytes29) - { - uint256 _loc = loc(memView); - - // Ensure it doesn't overrun the view - if (_loc.add(_index).add(_len) > end(memView)) { - return NULL; - } - - _loc = _loc.add(_index); - return build(newType, _loc, _len); - } - - /** - * @notice Shortcut to `slice`. Gets a view representing the first `_len` bytes. - * @param memView The view - * @param _len The length - * @param newType The new type - * @return bytes29 - The new view - */ - function prefix(bytes29 memView, uint256 _len, uint40 newType) internal pure returns (bytes29) { - return slice(memView, 0, _len, newType); - } - - /** - * @notice Shortcut to `slice`. Gets a view representing the last `_len` byte. - * @param memView The view - * @param _len The length - * @param newType The new type - * @return bytes29 - The new view - */ - function postfix(bytes29 memView, uint256 _len, uint40 newType) internal pure returns (bytes29) { - return slice(memView, uint256(len(memView)).sub(_len), _len, newType); - } - - /** - * @notice Construct an error message for an indexing overrun. - * @param _loc The memory address - * @param _len The length - * @param _index The index - * @param _slice The slice where the overrun occurred - * @return err - The err - */ - function indexErrOverrun(uint256 _loc, uint256 _len, uint256 _index, uint256 _slice) - internal - pure - returns (string memory err) - { - (, uint256 a) = encodeHex(_loc); - (, uint256 b) = encodeHex(_len); - (, uint256 c) = encodeHex(_index); - (, uint256 d) = encodeHex(_slice); - err = string( - abi.encodePacked( - "TypedMemView/index - Overran the view. Slice is at 0x", - uint48(a), - " with length 0x", - uint48(b), - ". Attempted to index at offset 0x", - uint48(c), - " with length 0x", - uint48(d), - "." - ) - ); - } - - /** - * @notice Load up to 32 bytes from the view onto the stack. - * @dev Returns a bytes32 with only the `_bytes` highest bytes set. - * This can be immediately cast to a smaller fixed-length byte array. - * To automatically cast to an integer, use `indexUint`. - * @param memView The view - * @param _index The index - * @param _bytes The bytes - * @return result - The 32 byte result - */ - function index(bytes29 memView, uint256 _index, uint8 _bytes) - internal - pure - returns (bytes32 result) - { - if (_bytes == 0) { - return bytes32(0); - } - if (_index.add(_bytes) > len(memView)) { - revert(indexErrOverrun(loc(memView), len(memView), _index, uint256(_bytes))); - } - require(_bytes <= 32, "TypedMemView/index - Attempted to index more than 32 bytes"); - - uint8 bitLength = _bytes * 8; - uint256 _loc = loc(memView); - uint256 _mask = leftMask(bitLength); - assembly { - // solium-disable-previous-line security/no-inline-assembly - result := and(mload(add(_loc, _index)), _mask) - } - } - - /** - * @notice Parse an unsigned integer from the view at `_index`. - * @dev Requires that the view have >= `_bytes` bytes following that index. - * @param memView The view - * @param _index The index - * @param _bytes The bytes - * @return result - The unsigned integer - */ - function indexUint(bytes29 memView, uint256 _index, uint8 _bytes) - internal - pure - returns (uint256 result) - { - return uint256(index(memView, _index, _bytes)) >> ((32 - _bytes) * 8); - } - - /** - * @notice Parse an unsigned integer from LE bytes. - * @param memView The view - * @param _index The index - * @param _bytes The bytes - * @return result - The unsigned integer - */ - function indexLEUint(bytes29 memView, uint256 _index, uint8 _bytes) - internal - pure - returns (uint256 result) - { - return reverseUint256(uint256(index(memView, _index, _bytes))); - } - - /** - * @notice Parse an address from the view at `_index`. Requires that the view have >= 20 bytes - * following that index. - * @param memView The view - * @param _index The index - * @return address - The address - */ - function indexAddress(bytes29 memView, uint256 _index) internal pure returns (address) { - return address(uint160(indexUint(memView, _index, 20))); - } - - /** - * @notice Return the keccak256 hash of the underlying memory - * @param memView The view - * @return digest - The keccak256 hash of the underlying memory - */ - function keccak(bytes29 memView) internal pure returns (bytes32 digest) { - uint256 _loc = loc(memView); - uint256 _len = len(memView); - assembly { - // solium-disable-previous-line security/no-inline-assembly - digest := keccak256(_loc, _len) - } - } - - /** - * @notice Return the sha2 digest of the underlying memory. - * @dev We explicitly deallocate memory afterwards. - * @param memView The view - * @return digest - The sha2 hash of the underlying memory - */ - function sha2(bytes29 memView) internal view returns (bytes32 digest) { - uint256 _loc = loc(memView); - uint256 _len = len(memView); - - bool res; - assembly { - // solium-disable-previous-line security/no-inline-assembly - let ptr := mload(0x40) - res := staticcall(gas, 2, _loc, _len, ptr, 0x20) // sha2 #1 - digest := mload(ptr) - } - require(res, "sha2 OOG"); - } - - /** - * @notice Implements bitcoin's hash160 (rmd160(sha2())) - * @param memView The pre-image - * @return digest - the Digest - */ - function hash160(bytes29 memView) internal view returns (bytes20 digest) { - uint256 _loc = loc(memView); - uint256 _len = len(memView); - bool res; - assembly { - // solium-disable-previous-line security/no-inline-assembly - let ptr := mload(0x40) - res := staticcall(gas, 2, _loc, _len, ptr, 0x20) // sha2 - res := and(res, staticcall(gas, 3, ptr, 0x20, ptr, 0x20)) // rmd160 - digest := mload(add(ptr, 0xc)) // return value is 0-prefixed. - } - require(res, "hash160 OOG"); - } - - /** - * @notice Implements bitcoin's hash256 (double sha2) - * @param memView A view of the preimage - * @return digest - the Digest - */ - function hash256(bytes29 memView) internal view returns (bytes32 digest) { - uint256 _loc = loc(memView); - uint256 _len = len(memView); - bool res; - assembly { - // solium-disable-previous-line security/no-inline-assembly - let ptr := mload(0x40) - res := staticcall(gas, 2, _loc, _len, ptr, 0x20) // sha2 #1 - res := and(res, staticcall(gas, 2, ptr, 0x20, ptr, 0x20)) // sha2 #2 - digest := mload(ptr) - } - require(res, "hash256 OOG"); - } - - /** - * @notice Return true if the underlying memory is equal. Else false. - * @param left The first view - * @param right The second view - * @return bool - True if the underlying memory is equal - */ - function untypedEqual(bytes29 left, bytes29 right) internal pure returns (bool) { - return (loc(left) == loc(right) && len(left) == len(right)) || keccak(left) == keccak(right); - } - - /** - * @notice Return false if the underlying memory is equal. Else true. - * @param left The first view - * @param right The second view - * @return bool - False if the underlying memory is equal - */ - function untypedNotEqual(bytes29 left, bytes29 right) internal pure returns (bool) { - return !untypedEqual(left, right); - } - - /** - * @notice Compares type equality. - * @dev Shortcuts if the pointers are identical, otherwise compares type and digest. - * @param left The first view - * @param right The second view - * @return bool - True if the types are the same - */ - function equal(bytes29 left, bytes29 right) internal pure returns (bool) { - return left == right || (typeOf(left) == typeOf(right) && keccak(left) == keccak(right)); - } - - /** - * @notice Compares type inequality. - * @dev Shortcuts if the pointers are identical, otherwise compares type and digest. - * @param left The first view - * @param right The second view - * @return bool - True if the types are not the same - */ - function notEqual(bytes29 left, bytes29 right) internal pure returns (bool) { - return !equal(left, right); - } - - /** - * @notice Copy the view to a location, return an unsafe memory reference - * @dev Super Dangerous direct memory access. - * - * This reference can be overwritten if anything else modifies memory (!!!). - * As such it MUST be consumed IMMEDIATELY. - * This function is private to prevent unsafe usage by callers. - * @param memView The view - * @param _newLoc The new location - * @return written - the unsafe memory reference - */ - function unsafeCopyTo(bytes29 memView, uint256 _newLoc) private view returns (bytes29 written) { - require(notNull(memView), "TypedMemView/copyTo - Null pointer deref"); - require(isValid(memView), "TypedMemView/copyTo - Invalid pointer deref"); - uint256 _len = len(memView); - uint256 _oldLoc = loc(memView); - - uint256 ptr; - bool res; - assembly { - // solium-disable-previous-line security/no-inline-assembly - ptr := mload(0x40) - // revert if we're writing in occupied memory - if gt(ptr, _newLoc) { - revert(0x60, 0x20) // empty revert message - } - - // use the identity precompile to copy - res := staticcall(gas, 4, _oldLoc, _len, _newLoc, _len) - } - require(res, "identity OOG"); - written = unsafeBuildUnchecked(typeOf(memView), _newLoc, _len); - } - - /** - * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to - * the new memory - * @dev Shortcuts if the pointers are identical, otherwise compares type and digest. - * @param memView The view - * @return ret - The view pointing to the new memory - */ - function clone(bytes29 memView) internal view returns (bytes memory ret) { - uint256 ptr; - uint256 _len = len(memView); - assembly { - // solium-disable-previous-line security/no-inline-assembly - ptr := mload(0x40) // load unused memory pointer - ret := ptr - } - unsafeCopyTo(memView, ptr + 0x20); - assembly { - // solium-disable-previous-line security/no-inline-assembly - mstore(0x40, add(add(ptr, _len), 0x20)) // write new unused pointer - mstore(ptr, _len) // write len of new array (in bytes) - } - } - - /** - * @notice Join the views in memory, return an unsafe reference to the memory. - * @dev Super Dangerous direct memory access. - * - * This reference can be overwritten if anything else modifies memory (!!!). - * As such it MUST be consumed IMMEDIATELY. - * This function is private to prevent unsafe usage by callers. - * @param memViews The views - * @param _location The location in memory to which to copy & concatenate - * @return unsafeView - The conjoined view pointing to the new memory - */ - function unsafeJoin(bytes29[] memory memViews, uint256 _location) - private - view - returns (bytes29 unsafeView) - { - assembly { - // solium-disable-previous-line security/no-inline-assembly - let ptr := mload(0x40) - // revert if we're writing in occupied memory - if gt(ptr, _location) { - revert(0x60, 0x20) // empty revert message - } - } - - uint256 _offset = 0; - for (uint256 i = 0; i < memViews.length; i++) { - bytes29 memView = memViews[i]; - unsafeCopyTo(memView, _location + _offset); - _offset += len(memView); - } - unsafeView = unsafeBuildUnchecked(0, _location, _offset); - } - - /** - * @notice Produce the keccak256 digest of the concatenated contents of multiple views. - * @param memViews The views - * @return bytes32 - The keccak256 digest - */ - function joinKeccak(bytes29[] memory memViews) internal view returns (bytes32) { - uint256 ptr; - assembly { - // solium-disable-previous-line security/no-inline-assembly - ptr := mload(0x40) // load unused memory pointer - } - return keccak(unsafeJoin(memViews, ptr)); - } - - /** - * @notice Produce the sha256 digest of the concatenated contents of multiple views. - * @param memViews The views - * @return bytes32 - The sha256 digest - */ - function joinSha2(bytes29[] memory memViews) internal view returns (bytes32) { - uint256 ptr; - assembly { - // solium-disable-previous-line security/no-inline-assembly - ptr := mload(0x40) // load unused memory pointer - } - return sha2(unsafeJoin(memViews, ptr)); - } - - /** - * @notice copies all views, joins them into a new bytearray. - * @param memViews The views - * @return ret - The new byte array - */ - function join(bytes29[] memory memViews) internal view returns (bytes memory ret) { - uint256 ptr; - assembly { - // solium-disable-previous-line security/no-inline-assembly - ptr := mload(0x40) // load unused memory pointer - } - - bytes29 _newView = unsafeJoin(memViews, ptr + 0x20); - uint256 _written = len(_newView); - uint256 _footprint = footprint(_newView); - - assembly { - // solium-disable-previous-line security/no-inline-assembly - // store the legnth - mstore(ptr, _written) - // new pointer is old + 0x20 + the footprint of the body - mstore(0x40, add(add(ptr, _footprint), 0x20)) - ret := ptr - } - } -} diff --git a/packages/protocol/contracts/common/libraries/test/BLS12Passthrough.sol b/packages/protocol/contracts/common/libraries/test/BLS12Passthrough.sol deleted file mode 100644 index b2da0bdb3..000000000 --- a/packages/protocol/contracts/common/libraries/test/BLS12Passthrough.sol +++ /dev/null @@ -1,332 +0,0 @@ -pragma solidity ^0.5.13; - -import { B12_377Lib, B12_381Lib, B12 } from "../B12.sol"; -import { TypedMemView } from "../TypedMemView.sol"; - -contract Common { - using B12 for B12.G1Point; - using B12 for B12.G2Point; - using B12 for B12.Fp; - using B12 for B12.Fp2; - using B12 for bytes; - - using TypedMemView for bytes; - using TypedMemView for bytes29; - - constructor() public {} - function testParseG1(bytes calldata arg) external pure returns (uint256[4] memory ret) { - B12.G1Point memory a = arg.parseG1(0); - ret[0] = a.X.a; - ret[1] = a.X.b; - ret[2] = a.Y.a; - ret[3] = a.Y.b; - } - - function testSerializeG1(uint256 w, uint256 x, uint256 y, uint256 z) - external - pure - returns (bytes memory) - { - B12.G1Point memory a; - a.X.a = w; - a.X.b = x; - a.Y.a = y; - a.Y.b = z; - - return a.serializeG1(); - } - - function testParseG2(bytes calldata arg) external pure returns (uint256[8] memory ret) { - B12.G2Point memory a = arg.parseG2(0); - ret[0] = a.X.a.a; - ret[1] = a.X.a.b; - ret[2] = a.X.b.a; - ret[3] = a.X.b.b; - ret[4] = a.Y.a.a; - ret[5] = a.Y.a.b; - ret[6] = a.Y.b.a; - ret[7] = a.Y.b.b; - } - - function testSerializeG2( - uint256 xaa, - uint256 xab, - uint256 xba, - uint256 xbb, - uint256 yaa, - uint256 yab, - uint256 yba, - uint256 ybb - ) external pure returns (bytes memory) { - B12.G2Point memory a; - a.X.a.a = xaa; - a.X.a.b = xab; - a.X.b.a = xba; - a.X.b.b = xbb; - a.Y.a.a = yaa; - a.Y.a.b = yab; - a.Y.b.a = yba; - a.Y.b.b = ybb; - - return a.serializeG2(); - } - - function fpMulTest(uint256 a1, uint256 a2, uint256 b1, uint256 b2) - external - view - returns (uint256, uint256) - { - B12.Fp memory a = B12.Fp(a1, a2); - B12.Fp memory b = B12.Fp(b1, b2); - B12.Fp memory res = B12.fpMul(a, b); - return (res.a, res.b); - } - - function fpNormalTest(uint256 a1, uint256 a2) external view returns (uint256, uint256) { - B12.Fp memory a = B12.Fp(a1, a2); - B12.Fp memory res = B12.fpNormal(a); - return (res.a, res.b); - } - - function fpNormal2Test(uint256 a, uint256 idx) external view returns (uint256, uint256) { - B12.Fp memory res = B12.fpNormal2(B12.Fp(0, a), idx); - return (res.a, res.b); - } - - function fp2MulTest(uint256[] calldata arr) - external - view - returns (uint256, uint256, uint256, uint256) - { - B12.Fp2 memory x = B12.Fp2(B12.Fp(arr[0], arr[1]), B12.Fp(arr[2], arr[3])); - B12.Fp2 memory y = B12.Fp2(B12.Fp(arr[4], arr[5]), B12.Fp(arr[6], arr[7])); - B12.Fp2 memory res = B12.fp2Mul(x, y); - return (res.a.a, res.a.b, res.b.a, res.b.b); - } - - function testUncompress() external view returns (uint256, uint256) { - B12.Fp memory x = B12.Fp( - 0x008848defe740a67c8fc6225bf87ff54, - 0x85951e2caa9d41bb188282c8bd37cb5cd5481512ffcd394eeab9b16eb21be9ef - ); - B12.Fp memory y1 = B12.Fp( - 0x001cefdc52b4e1eba6d3b6633bf15a76, - 0x5ca326aa36b6c0b5b1db375b6a5124fa540d200dfb56a6e58785e1aaaa63715b - ); - B12.Fp memory y2 = B12.Fp( - 0x01914a69c5102eff1f674f5d30afeec4, - 0xbd7fb348ca3e52d96d182ad44fb82305c2fe3d3634a9591afd82de55559c8ea6 - ); - B12.G1Point memory res = B12.mapToG1(x, y2, y1, true); - return (res.Y.a, res.Y.b); - } - - function testDeserialize(bytes memory h) public pure returns (uint256, uint256, bool) { - (B12.Fp memory p, bool b) = B12.parsePoint(h); - return (p.a, p.b, b); - } - - event MEMDUMP(uint256 a, uint256 b, uint256 c, uint256 d); - - function dumpMem(uint256 idx) internal { - uint256 a; - uint256 b; - uint256 c; - uint256 d; - - assembly { - a := mload(add(idx, 0x00)) - b := mload(add(idx, 0x20)) - c := mload(add(idx, 0x40)) - d := mload(add(idx, 0x60)) - } - emit MEMDUMP(a, b, c, d); - } - - function executePrecompile(bytes memory input, uint8 addr, uint256 output_len) - internal - view - returns (bytes memory output) - { - bool success; - assembly { - success := staticcall( - sub(gas, 2000), - addr, - add(input, 0x20), // location - mload(input), // length - add(output, 0x20), // location - output_len // length - ) - mstore(output, output_len) - } - - require(success, "failed"); - } -} - -contract BLS12_381Passthrough is Common { - using B12_381Lib for B12.G1Point; - using B12_381Lib for B12.G2Point; - using B12_381Lib for B12.Fp; - using B12_381Lib for B12.Fp2; - using B12 for B12.G1Point; - using B12 for B12.G2Point; - using B12 for B12.Fp; - using B12 for B12.Fp2; - using B12_381Lib for bytes; - using B12 for bytes; - - using TypedMemView for bytes; - using TypedMemView for bytes29; - - constructor() public {} - - function g1Add(bytes calldata args) external view returns (bytes memory) { - B12.G1Point memory a = args.parseG1(0); - B12.G1Point memory b = args.parseG1(4 * 32); - return a.g1Add(b).serializeG1(); - } - - function g1Mul(bytes calldata args) external view returns (bytes memory) { - B12.G1Point memory a = args.parseG1(0); - uint256 scalar = args.ref(0).indexUint(4 * 32, 32); - return a.g1Mul(scalar).serializeG1(); - } - - function g1MultiExp(bytes calldata args) external view returns (bytes memory) { - bytes29 ref = args.ref(0); - - B12.G1MultiExpArg[] memory input = new B12.G1MultiExpArg[](args.length / 160); - - for (uint256 i = 0; i < args.length / 160; i += 1) { - uint256 idx = i * 160; - - input[i].point.X.a = ref.indexUint(idx + 0x00, 32); - input[i].point.X.b = ref.indexUint(idx + 0x20, 32); - input[i].point.Y.a = ref.indexUint(idx + 0x40, 32); - input[i].point.Y.b = ref.indexUint(idx + 0x60, 32); - input[i].scalar = ref.indexUint(idx + 0x80, 32); - } - - return B12_381Lib.g1MultiExp(input).serializeG1(); - } - - function g2Add(bytes calldata args) external view returns (bytes memory) { - B12.G2Point memory a = args.parseG2(0); - B12.G2Point memory b = args.parseG2(8 * 32); - return a.g2Add(b).serializeG2(); - } - - function g2Mul(bytes calldata args) external view returns (bytes memory) { - B12.G2Point memory a = args.parseG2(0); - uint256 scalar = args.ref(0).indexUint(8 * 32, 32); - a.g2Mul(scalar); - return a.serializeG2(); - } - - function g2MultiExp(bytes calldata args) external view returns (bytes memory) { - bytes29 ref = args.ref(0); - - B12.G2MultiExpArg[] memory input = new B12.G2MultiExpArg[](args.length / 288); - - for (uint256 i = 0; i < args.length / 288; i += 1) { - uint256 idx = i * 288; - - input[i].point.X.a.a = ref.indexUint(idx + 0x00, 32); - input[i].point.X.a.b = ref.indexUint(idx + 0x20, 32); - input[i].point.X.b.a = ref.indexUint(idx + 0x40, 32); - input[i].point.X.b.b = ref.indexUint(idx + 0x60, 32); - input[i].point.Y.a.a = ref.indexUint(idx + 0x80, 32); - input[i].point.Y.a.b = ref.indexUint(idx + 0xa0, 32); - input[i].point.Y.b.a = ref.indexUint(idx + 0xc0, 32); - input[i].point.Y.b.b = ref.indexUint(idx + 0xe0, 32); - input[i].scalar = ref.indexUint(idx + 0x100, 32); - } - - return B12_381Lib.g2MultiExp(input).serializeG2(); - } -} - -contract BLS12_377Passthrough is Common { - using B12_377Lib for B12.G1Point; - using B12_377Lib for B12.G2Point; - using B12_377Lib for B12.Fp; - using B12_377Lib for B12.Fp2; - using B12 for B12.G1Point; - using B12 for B12.G2Point; - using B12 for B12.Fp; - using B12 for B12.Fp2; - using B12_377Lib for bytes; - using B12 for bytes; - - using TypedMemView for bytes; - using TypedMemView for bytes29; - - constructor() public {} - - function g1Add(bytes calldata args) external view returns (bytes memory) { - B12.G1Point memory a = args.parseG1(0); - B12.G1Point memory b = args.parseG1(4 * 32); - return a.g1Add(b).serializeG1(); - } - - function g1Mul(bytes calldata args) external view returns (bytes memory) { - B12.G1Point memory a = args.parseG1(0); - uint256 scalar = args.ref(0).indexUint(4 * 32, 32); - return a.g1Mul(scalar).serializeG1(); - } - - function g1MultiExp(bytes calldata args) external view returns (bytes memory) { - bytes29 ref = args.ref(0); - - B12.G1MultiExpArg[] memory input = new B12.G1MultiExpArg[](args.length / 160); - - for (uint256 i = 0; i < args.length / 160; i += 1) { - uint256 idx = i * 160; - - input[i].point.X.a = ref.indexUint(idx + 0x00, 32); - input[i].point.X.b = ref.indexUint(idx + 0x20, 32); - input[i].point.Y.a = ref.indexUint(idx + 0x40, 32); - input[i].point.Y.b = ref.indexUint(idx + 0x60, 32); - input[i].scalar = ref.indexUint(idx + 0x80, 32); - } - - return B12_377Lib.g1MultiExp(input).serializeG1(); - } - - function g2Add(bytes calldata args) external view returns (bytes memory) { - B12.G2Point memory a = args.parseG2(0); - B12.G2Point memory b = args.parseG2(8 * 32); - return a.g2Add(b).serializeG2(); - } - - function g2Mul(bytes calldata args) external view returns (bytes memory) { - B12.G2Point memory a = args.parseG2(0); - uint256 scalar = args.ref(0).indexUint(8 * 32, 32); - a.g2Mul(scalar); - return a.serializeG2(); - } - - function g2MultiExp(bytes calldata args) external view returns (bytes memory) { - bytes29 ref = args.ref(0); - - B12.G2MultiExpArg[] memory input = new B12.G2MultiExpArg[](args.length / 288); - - for (uint256 i = 0; i < args.length / 288; i += 1) { - uint256 idx = i * 288; - - input[i].point.X.a.a = ref.indexUint(idx + 0x00, 32); - input[i].point.X.a.b = ref.indexUint(idx + 0x20, 32); - input[i].point.X.b.a = ref.indexUint(idx + 0x40, 32); - input[i].point.X.b.b = ref.indexUint(idx + 0x60, 32); - input[i].point.Y.a.a = ref.indexUint(idx + 0x80, 32); - input[i].point.Y.a.b = ref.indexUint(idx + 0xa0, 32); - input[i].point.Y.b.a = ref.indexUint(idx + 0xc0, 32); - input[i].point.Y.b.b = ref.indexUint(idx + 0xe0, 32); - input[i].scalar = ref.indexUint(idx + 0x100, 32); - } - - return B12_377Lib.g2MultiExp(input).serializeG2(); - } -} diff --git a/packages/protocol/contracts/common/libraries/test/CIP20Test.sol b/packages/protocol/contracts/common/libraries/test/CIP20Test.sol deleted file mode 100644 index 79a42349f..000000000 --- a/packages/protocol/contracts/common/libraries/test/CIP20Test.sol +++ /dev/null @@ -1,35 +0,0 @@ -pragma solidity ^0.5.13; - -import "../CIP20Lib.sol"; - -contract CIP20Test { - using CIP20Lib for bytes; - - function sha3_256(bytes calldata input) external view returns (bytes memory) { - return input.sha3_256(); - } - - function sha3_512(bytes calldata input) external view returns (bytes memory) { - return input.sha3_512(); - } - - function keccak512(bytes calldata input) external view returns (bytes memory) { - return input.keccak512(); - } - - function sha2_512(bytes calldata input) external view returns (bytes memory) { - return input.sha2_512(); - } - - function blake2sWithConfig(bytes32 config, bytes calldata key, bytes calldata preimage) - external - view - returns (bytes memory) - { - return CIP20Lib.blake2sWithConfig(config, key, preimage); - } - - function blake2s(bytes calldata input) external view returns (bytes memory) { - return input.blake2s(); - } -} diff --git a/packages/protocol/contracts/common/linkedlists/AddressLinkedList.sol b/packages/protocol/contracts/common/linkedlists/AddressLinkedList.sol deleted file mode 100644 index 5f5bef012..000000000 --- a/packages/protocol/contracts/common/linkedlists/AddressLinkedList.sol +++ /dev/null @@ -1,101 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; - -import "./LinkedList.sol"; - -/** - * @title Maintains a doubly linked list keyed by address. - * @dev Following the `next` pointers will lead you to the head, rather than the tail. - */ -library AddressLinkedList { - using LinkedList for LinkedList.List; - using SafeMath for uint256; - - function toBytes(address a) public pure returns (bytes32) { - return bytes32(uint256(a) << 96); - } - - function toAddress(bytes32 b) public pure returns (address) { - return address(uint256(b) >> 96); - } - - /** - * @notice Inserts an element into a doubly linked list. - * @param list A storage pointer to the underlying list. - * @param key The key of the element to insert. - * @param previousKey The key of the element that comes before the element to insert. - * @param nextKey The key of the element that comes after the element to insert. - */ - function insert(LinkedList.List storage list, address key, address previousKey, address nextKey) - public - { - list.insert(toBytes(key), toBytes(previousKey), toBytes(nextKey)); - } - - /** - * @notice Inserts an element at the end of the doubly linked list. - * @param list A storage pointer to the underlying list. - * @param key The key of the element to insert. - */ - function push(LinkedList.List storage list, address key) public { - list.insert(toBytes(key), bytes32(0), list.tail); - } - - /** - * @notice Removes an element from the doubly linked list. - * @param list A storage pointer to the underlying list. - * @param key The key of the element to remove. - */ - function remove(LinkedList.List storage list, address key) public { - list.remove(toBytes(key)); - } - - /** - * @notice Updates an element in the list. - * @param list A storage pointer to the underlying list. - * @param key The element key. - * @param previousKey The key of the element that comes before the updated element. - * @param nextKey The key of the element that comes after the updated element. - */ - function update(LinkedList.List storage list, address key, address previousKey, address nextKey) - public - { - list.update(toBytes(key), toBytes(previousKey), toBytes(nextKey)); - } - - /** - * @notice Returns whether or not a particular key is present in the sorted list. - * @param list A storage pointer to the underlying list. - * @param key The element key. - * @return Whether or not the key is in the sorted list. - */ - function contains(LinkedList.List storage list, address key) public view returns (bool) { - return list.elements[toBytes(key)].exists; - } - - /** - * @notice Returns the N greatest elements of the list. - * @param list A storage pointer to the underlying list. - * @param n The number of elements to return. - * @return The keys of the greatest elements. - * @dev Reverts if n is greater than the number of elements in the list. - */ - function headN(LinkedList.List storage list, uint256 n) public view returns (address[] memory) { - bytes32[] memory byteKeys = list.headN(n); - address[] memory keys = new address[](n); - for (uint256 i = 0; i < n; i = i.add(1)) { - keys[i] = toAddress(byteKeys[i]); - } - return keys; - } - - /** - * @notice Gets all element keys from the doubly linked list. - * @param list A storage pointer to the underlying list. - * @return All element keys from head to tail. - */ - function getKeys(LinkedList.List storage list) public view returns (address[] memory) { - return headN(list, list.numElements); - } -} diff --git a/packages/protocol/contracts/common/linkedlists/AddressSortedLinkedList.sol b/packages/protocol/contracts/common/linkedlists/AddressSortedLinkedList.sol deleted file mode 100644 index 9f90b8764..000000000 --- a/packages/protocol/contracts/common/linkedlists/AddressSortedLinkedList.sol +++ /dev/null @@ -1,159 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/Math.sol"; -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; - -import "./SortedLinkedList.sol"; - -/** - * @title Maintains a sorted list of unsigned ints keyed by address. - */ -library AddressSortedLinkedList { - using SafeMath for uint256; - using SortedLinkedList for SortedLinkedList.List; - - function toBytes(address a) public pure returns (bytes32) { - return bytes32(uint256(a) << 96); - } - - function toAddress(bytes32 b) public pure returns (address) { - return address(uint256(b) >> 96); - } - - /** - * @notice Inserts an element into a doubly linked list. - * @param list A storage pointer to the underlying list. - * @param key The key of the element to insert. - * @param value The element value. - * @param lesserKey The key of the element less than the element to insert. - * @param greaterKey The key of the element greater than the element to insert. - */ - function insert( - SortedLinkedList.List storage list, - address key, - uint256 value, - address lesserKey, - address greaterKey - ) public { - list.insert(toBytes(key), value, toBytes(lesserKey), toBytes(greaterKey)); - } - - /** - * @notice Removes an element from the doubly linked list. - * @param list A storage pointer to the underlying list. - * @param key The key of the element to remove. - */ - function remove(SortedLinkedList.List storage list, address key) public { - list.remove(toBytes(key)); - } - - /** - * @notice Updates an element in the list. - * @param list A storage pointer to the underlying list. - * @param key The element key. - * @param value The element value. - * @param lesserKey The key of the element will be just left of `key` after the update. - * @param greaterKey The key of the element will be just right of `key` after the update. - * @dev Note that only one of "lesserKey" or "greaterKey" needs to be correct to reduce friction. - */ - function update( - SortedLinkedList.List storage list, - address key, - uint256 value, - address lesserKey, - address greaterKey - ) public { - list.update(toBytes(key), value, toBytes(lesserKey), toBytes(greaterKey)); - } - - /** - * @notice Returns whether or not a particular key is present in the sorted list. - * @param list A storage pointer to the underlying list. - * @param key The element key. - * @return Whether or not the key is in the sorted list. - */ - function contains(SortedLinkedList.List storage list, address key) public view returns (bool) { - return list.contains(toBytes(key)); - } - - /** - * @notice Returns the value for a particular key in the sorted list. - * @param list A storage pointer to the underlying list. - * @param key The element key. - * @return The element value. - */ - function getValue(SortedLinkedList.List storage list, address key) public view returns (uint256) { - return list.getValue(toBytes(key)); - } - - /** - * @notice Gets all elements from the doubly linked list. - * @return Array of all keys in the list. - * @return Values corresponding to keys, which will be ordered largest to smallest. - */ - function getElements(SortedLinkedList.List storage list) - public - view - returns (address[] memory, uint256[] memory) - { - bytes32[] memory byteKeys = list.getKeys(); - address[] memory keys = new address[](byteKeys.length); - uint256[] memory values = new uint256[](byteKeys.length); - for (uint256 i = 0; i < byteKeys.length; i = i.add(1)) { - keys[i] = toAddress(byteKeys[i]); - values[i] = list.values[byteKeys[i]]; - } - return (keys, values); - } - - /** - * @notice Returns the minimum of `max` and the number of elements in the list > threshold. - * @param list A storage pointer to the underlying list. - * @param threshold The number that the element must exceed to be included. - * @param max The maximum number returned by this function. - * @return The minimum of `max` and the number of elements in the list > threshold. - */ - function numElementsGreaterThan( - SortedLinkedList.List storage list, - uint256 threshold, - uint256 max - ) public view returns (uint256) { - uint256 revisedMax = Math.min(max, list.list.numElements); - bytes32 key = list.list.head; - for (uint256 i = 0; i < revisedMax; i = i.add(1)) { - if (list.getValue(key) < threshold) { - return i; - } - key = list.list.elements[key].previousKey; - } - return revisedMax; - } - - /** - * @notice Returns the N greatest elements of the list. - * @param list A storage pointer to the underlying list. - * @param n The number of elements to return. - * @return The keys of the greatest elements. - */ - function headN(SortedLinkedList.List storage list, uint256 n) - public - view - returns (address[] memory) - { - bytes32[] memory byteKeys = list.headN(n); - address[] memory keys = new address[](n); - for (uint256 i = 0; i < n; i = i.add(1)) { - keys[i] = toAddress(byteKeys[i]); - } - return keys; - } - - /** - * @notice Gets all element keys from the doubly linked list. - * @param list A storage pointer to the underlying list. - * @return All element keys from head to tail. - */ - function getKeys(SortedLinkedList.List storage list) public view returns (address[] memory) { - return headN(list, list.list.numElements); - } -} diff --git a/packages/protocol/contracts/common/linkedlists/AddressSortedLinkedListWithMedian.sol b/packages/protocol/contracts/common/linkedlists/AddressSortedLinkedListWithMedian.sol deleted file mode 100644 index 2a1f53907..000000000 --- a/packages/protocol/contracts/common/linkedlists/AddressSortedLinkedListWithMedian.sol +++ /dev/null @@ -1,174 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; - -import "./SortedLinkedListWithMedian.sol"; - -/** - * @title Maintains a sorted list of unsigned ints keyed by address. - */ -library AddressSortedLinkedListWithMedian { - using SafeMath for uint256; - using SortedLinkedListWithMedian for SortedLinkedListWithMedian.List; - - function toBytes(address a) public pure returns (bytes32) { - return bytes32(uint256(a) << 96); - } - - function toAddress(bytes32 b) public pure returns (address) { - return address(uint256(b) >> 96); - } - - /** - * @notice Inserts an element into a doubly linked list. - * @param list A storage pointer to the underlying list. - * @param key The key of the element to insert. - * @param value The element value. - * @param lesserKey The key of the element less than the element to insert. - * @param greaterKey The key of the element greater than the element to insert. - */ - function insert( - SortedLinkedListWithMedian.List storage list, - address key, - uint256 value, - address lesserKey, - address greaterKey - ) public { - list.insert(toBytes(key), value, toBytes(lesserKey), toBytes(greaterKey)); - } - - /** - * @notice Removes an element from the doubly linked list. - * @param list A storage pointer to the underlying list. - * @param key The key of the element to remove. - */ - function remove(SortedLinkedListWithMedian.List storage list, address key) public { - list.remove(toBytes(key)); - } - - /** - * @notice Updates an element in the list. - * @param list A storage pointer to the underlying list. - * @param key The element key. - * @param value The element value. - * @param lesserKey The key of the element will be just left of `key` after the update. - * @param greaterKey The key of the element will be just right of `key` after the update. - * @dev Note that only one of "lesserKey" or "greaterKey" needs to be correct to reduce friction. - */ - function update( - SortedLinkedListWithMedian.List storage list, - address key, - uint256 value, - address lesserKey, - address greaterKey - ) public { - list.update(toBytes(key), value, toBytes(lesserKey), toBytes(greaterKey)); - } - - /** - * @notice Returns whether or not a particular key is present in the sorted list. - * @param list A storage pointer to the underlying list. - * @param key The element key. - * @return Whether or not the key is in the sorted list. - */ - function contains(SortedLinkedListWithMedian.List storage list, address key) - public - view - returns (bool) - { - return list.contains(toBytes(key)); - } - - /** - * @notice Returns the value for a particular key in the sorted list. - * @param list A storage pointer to the underlying list. - * @param key The element key. - * @return The element value. - */ - function getValue(SortedLinkedListWithMedian.List storage list, address key) - public - view - returns (uint256) - { - return list.getValue(toBytes(key)); - } - - /** - * @notice Returns the median value of the sorted list. - * @param list A storage pointer to the underlying list. - * @return The median value. - */ - function getMedianValue(SortedLinkedListWithMedian.List storage list) - public - view - returns (uint256) - { - return list.getValue(list.median); - } - - /** - * @notice Returns the key of the first element in the list. - * @param list A storage pointer to the underlying list. - * @return The key of the first element in the list. - */ - function getHead(SortedLinkedListWithMedian.List storage list) external view returns (address) { - return toAddress(list.getHead()); - } - - /** - * @notice Returns the key of the median element in the list. - * @param list A storage pointer to the underlying list. - * @return The key of the median element in the list. - */ - function getMedian(SortedLinkedListWithMedian.List storage list) external view returns (address) { - return toAddress(list.getMedian()); - } - - /** - * @notice Returns the key of the last element in the list. - * @param list A storage pointer to the underlying list. - * @return The key of the last element in the list. - */ - function getTail(SortedLinkedListWithMedian.List storage list) external view returns (address) { - return toAddress(list.getTail()); - } - - /** - * @notice Returns the number of elements in the list. - * @param list A storage pointer to the underlying list. - * @return The number of elements in the list. - */ - function getNumElements(SortedLinkedListWithMedian.List storage list) - external - view - returns (uint256) - { - return list.getNumElements(); - } - - /** - * @notice Gets all elements from the doubly linked list. - * @param list A storage pointer to the underlying list. - * @return Array of all keys in the list. - * @return Values corresponding to keys, which will be ordered largest to smallest. - * @return Array of relations to median of corresponding list elements. - */ - function getElements(SortedLinkedListWithMedian.List storage list) - public - view - returns (address[] memory, uint256[] memory, SortedLinkedListWithMedian.MedianRelation[] memory) - { - bytes32[] memory byteKeys = list.getKeys(); - address[] memory keys = new address[](byteKeys.length); - uint256[] memory values = new uint256[](byteKeys.length); - // prettier-ignore - SortedLinkedListWithMedian.MedianRelation[] memory relations = - new SortedLinkedListWithMedian.MedianRelation[](keys.length); - for (uint256 i = 0; i < byteKeys.length; i = i.add(1)) { - keys[i] = toAddress(byteKeys[i]); - values[i] = list.getValue(byteKeys[i]); - relations[i] = list.relation[byteKeys[i]]; - } - return (keys, values, relations); - } -} diff --git a/packages/protocol/contracts/common/linkedlists/IntegerSortedLinkedList.sol b/packages/protocol/contracts/common/linkedlists/IntegerSortedLinkedList.sol deleted file mode 100644 index a5123ac51..000000000 --- a/packages/protocol/contracts/common/linkedlists/IntegerSortedLinkedList.sol +++ /dev/null @@ -1,124 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; - -import "./SortedLinkedList.sol"; - -/** - * @title Maintains a sorted list of unsigned ints keyed by uint256. - */ -library IntegerSortedLinkedList { - using SafeMath for uint256; - using SortedLinkedList for SortedLinkedList.List; - - /** - * @notice Inserts an element into a doubly linked list. - * @param list A storage pointer to the underlying list. - * @param key The key of the element to insert. - * @param value The element value. - * @param lesserKey The key of the element less than the element to insert. - * @param greaterKey The key of the element greater than the element to insert. - */ - function insert( - SortedLinkedList.List storage list, - uint256 key, - uint256 value, - uint256 lesserKey, - uint256 greaterKey - ) public { - list.insert(bytes32(key), value, bytes32(lesserKey), bytes32(greaterKey)); - } - - /** - * @notice Removes an element from the doubly linked list. - * @param list A storage pointer to the underlying list. - * @param key The key of the element to remove. - */ - function remove(SortedLinkedList.List storage list, uint256 key) public { - list.remove(bytes32(key)); - } - - /** - * @notice Updates an element in the list. - * @param list A storage pointer to the underlying list. - * @param key The element key. - * @param value The element value. - * @param lesserKey The key of the element will be just left of `key` after the update. - * @param greaterKey The key of the element will be just right of `key` after the update. - * @dev Note that only one of "lesserKey" or "greaterKey" needs to be correct to reduce friction. - */ - function update( - SortedLinkedList.List storage list, - uint256 key, - uint256 value, - uint256 lesserKey, - uint256 greaterKey - ) public { - list.update(bytes32(key), value, bytes32(lesserKey), bytes32(greaterKey)); - } - - /** - * @notice Inserts an element at the end of the doubly linked list. - * @param list A storage pointer to the underlying list. - * @param key The key of the element to insert. - */ - function push(SortedLinkedList.List storage list, uint256 key) public { - list.push(bytes32(key)); - } - - /** - * @notice Removes N elements from the head of the list and returns their keys. - * @param list A storage pointer to the underlying list. - * @param n The number of elements to pop. - * @return The keys of the popped elements. - */ - function popN(SortedLinkedList.List storage list, uint256 n) public returns (uint256[] memory) { - bytes32[] memory byteKeys = list.popN(n); - uint256[] memory keys = new uint256[](byteKeys.length); - for (uint256 i = 0; i < byteKeys.length; i = i.add(1)) { - keys[i] = uint256(byteKeys[i]); - } - return keys; - } - - /** - * @notice Returns whether or not a particular key is present in the sorted list. - * @param list A storage pointer to the underlying list. - * @param key The element key. - * @return Whether or not the key is in the sorted list. - */ - function contains(SortedLinkedList.List storage list, uint256 key) public view returns (bool) { - return list.contains(bytes32(key)); - } - - /** - * @notice Returns the value for a particular key in the sorted list. - * @param list A storage pointer to the underlying list. - * @param key The element key. - * @return The element value. - */ - function getValue(SortedLinkedList.List storage list, uint256 key) public view returns (uint256) { - return list.getValue(bytes32(key)); - } - - /** - * @notice Gets all elements from the doubly linked list. - * @param list A storage pointer to the underlying list. - * @return Array of all keys in the list. - * @return Values corresponding to keys, which will be ordered largest to smallest. - */ - function getElements(SortedLinkedList.List storage list) - public - view - returns (uint256[] memory, uint256[] memory) - { - bytes32[] memory byteKeys = list.getKeys(); - uint256[] memory keys = new uint256[](byteKeys.length); - uint256[] memory values = new uint256[](byteKeys.length); - for (uint256 i = 0; i < byteKeys.length; i = i.add(1)) { - keys[i] = uint256(byteKeys[i]); - values[i] = list.values[byteKeys[i]]; - } - return (keys, values); - } -} diff --git a/packages/protocol/contracts/common/linkedlists/LinkedList.sol b/packages/protocol/contracts/common/linkedlists/LinkedList.sol deleted file mode 100644 index 82b688ecc..000000000 --- a/packages/protocol/contracts/common/linkedlists/LinkedList.sol +++ /dev/null @@ -1,167 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; - -/** - * @title Maintains a doubly linked list keyed by bytes32. - * @dev Following the `next` pointers will lead you to the head, rather than the tail. - */ -library LinkedList { - using SafeMath for uint256; - - struct Element { - bytes32 previousKey; - bytes32 nextKey; - bool exists; - } - - struct List { - bytes32 head; - bytes32 tail; - uint256 numElements; - mapping(bytes32 => Element) elements; - } - - /** - * @notice Inserts an element into a doubly linked list. - * @param list A storage pointer to the underlying list. - * @param key The key of the element to insert. - * @param previousKey The key of the element that comes before the element to insert. - * @param nextKey The key of the element that comes after the element to insert. - */ - function insert(List storage list, bytes32 key, bytes32 previousKey, bytes32 nextKey) internal { - require(key != bytes32(0), "Key must be defined"); - require(!contains(list, key), "Can't insert an existing element"); - require( - previousKey != key && nextKey != key, - "Key cannot be the same as previousKey or nextKey" - ); - - Element storage element = list.elements[key]; - element.exists = true; - - if (list.numElements == 0) { - list.tail = key; - list.head = key; - } else { - require( - previousKey != bytes32(0) || nextKey != bytes32(0), - "Either previousKey or nextKey must be defined" - ); - - element.previousKey = previousKey; - element.nextKey = nextKey; - - if (previousKey != bytes32(0)) { - require( - contains(list, previousKey), - "If previousKey is defined, it must exist in the list" - ); - Element storage previousElement = list.elements[previousKey]; - require(previousElement.nextKey == nextKey, "previousKey must be adjacent to nextKey"); - previousElement.nextKey = key; - } else { - list.tail = key; - } - - if (nextKey != bytes32(0)) { - require(contains(list, nextKey), "If nextKey is defined, it must exist in the list"); - Element storage nextElement = list.elements[nextKey]; - require(nextElement.previousKey == previousKey, "previousKey must be adjacent to nextKey"); - nextElement.previousKey = key; - } else { - list.head = key; - } - } - - list.numElements = list.numElements.add(1); - } - - /** - * @notice Inserts an element at the tail of the doubly linked list. - * @param list A storage pointer to the underlying list. - * @param key The key of the element to insert. - */ - function push(List storage list, bytes32 key) internal { - insert(list, key, bytes32(0), list.tail); - } - - /** - * @notice Removes an element from the doubly linked list. - * @param list A storage pointer to the underlying list. - * @param key The key of the element to remove. - */ - function remove(List storage list, bytes32 key) internal { - Element storage element = list.elements[key]; - require(key != bytes32(0) && contains(list, key), "key not in list"); - if (element.previousKey != bytes32(0)) { - Element storage previousElement = list.elements[element.previousKey]; - previousElement.nextKey = element.nextKey; - } else { - list.tail = element.nextKey; - } - - if (element.nextKey != bytes32(0)) { - Element storage nextElement = list.elements[element.nextKey]; - nextElement.previousKey = element.previousKey; - } else { - list.head = element.previousKey; - } - - delete list.elements[key]; - list.numElements = list.numElements.sub(1); - } - - /** - * @notice Updates an element in the list. - * @param list A storage pointer to the underlying list. - * @param key The element key. - * @param previousKey The key of the element that comes before the updated element. - * @param nextKey The key of the element that comes after the updated element. - */ - function update(List storage list, bytes32 key, bytes32 previousKey, bytes32 nextKey) internal { - require( - key != bytes32(0) && key != previousKey && key != nextKey && contains(list, key), - "key on in list" - ); - remove(list, key); - insert(list, key, previousKey, nextKey); - } - - /** - * @notice Returns whether or not a particular key is present in the sorted list. - * @param list A storage pointer to the underlying list. - * @param key The element key. - * @return Whether or not the key is in the sorted list. - */ - function contains(List storage list, bytes32 key) internal view returns (bool) { - return list.elements[key].exists; - } - - /** - * @notice Returns the keys of the N elements at the head of the list. - * @param list A storage pointer to the underlying list. - * @param n The number of elements to return. - * @return The keys of the N elements at the head of the list. - * @dev Reverts if n is greater than the number of elements in the list. - */ - function headN(List storage list, uint256 n) internal view returns (bytes32[] memory) { - require(n <= list.numElements, "not enough elements"); - bytes32[] memory keys = new bytes32[](n); - bytes32 key = list.head; - for (uint256 i = 0; i < n; i = i.add(1)) { - keys[i] = key; - key = list.elements[key].previousKey; - } - return keys; - } - - /** - * @notice Gets all element keys from the doubly linked list. - * @param list A storage pointer to the underlying list. - * @return All element keys from head to tail. - */ - function getKeys(List storage list) internal view returns (bytes32[] memory) { - return headN(list, list.numElements); - } -} diff --git a/packages/protocol/contracts/common/linkedlists/SortedLinkedList.sol b/packages/protocol/contracts/common/linkedlists/SortedLinkedList.sol deleted file mode 100644 index 25f92fcb2..000000000 --- a/packages/protocol/contracts/common/linkedlists/SortedLinkedList.sol +++ /dev/null @@ -1,221 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "./LinkedList.sol"; - -/** - * @title Maintains a sorted list of unsigned ints keyed by bytes32. - */ -library SortedLinkedList { - using SafeMath for uint256; - using LinkedList for LinkedList.List; - - struct List { - LinkedList.List list; - mapping(bytes32 => uint256) values; - } - - /** - * @notice Inserts an element into a doubly linked list. - * @param list A storage pointer to the underlying list. - * @param key The key of the element to insert. - * @param value The element value. - * @param lesserKey The key of the element less than the element to insert. - * @param greaterKey The key of the element greater than the element to insert. - */ - function insert( - List storage list, - bytes32 key, - uint256 value, - bytes32 lesserKey, - bytes32 greaterKey - ) internal { - require( - key != bytes32(0) && key != lesserKey && key != greaterKey && !contains(list, key), - "invalid key" - ); - require( - (lesserKey != bytes32(0) || greaterKey != bytes32(0)) || list.list.numElements == 0, - "greater and lesser key zero" - ); - require(contains(list, lesserKey) || lesserKey == bytes32(0), "invalid lesser key"); - require(contains(list, greaterKey) || greaterKey == bytes32(0), "invalid greater key"); - (lesserKey, greaterKey) = getLesserAndGreater(list, value, lesserKey, greaterKey); - list.list.insert(key, lesserKey, greaterKey); - list.values[key] = value; - } - - /** - * @notice Removes an element from the doubly linked list. - * @param list A storage pointer to the underlying list. - * @param key The key of the element to remove. - */ - function remove(List storage list, bytes32 key) internal { - list.list.remove(key); - list.values[key] = 0; - } - - /** - * @notice Updates an element in the list. - * @param list A storage pointer to the underlying list. - * @param key The element key. - * @param value The element value. - * @param lesserKey The key of the element will be just left of `key` after the update. - * @param greaterKey The key of the element will be just right of `key` after the update. - * @dev Note that only one of "lesserKey" or "greaterKey" needs to be correct to reduce friction. - */ - function update( - List storage list, - bytes32 key, - uint256 value, - bytes32 lesserKey, - bytes32 greaterKey - ) internal { - remove(list, key); - insert(list, key, value, lesserKey, greaterKey); - } - - /** - * @notice Inserts an element at the tail of the doubly linked list. - * @param list A storage pointer to the underlying list. - * @param key The key of the element to insert. - */ - function push(List storage list, bytes32 key) internal { - insert(list, key, 0, bytes32(0), list.list.tail); - } - - /** - * @notice Removes N elements from the head of the list and returns their keys. - * @param list A storage pointer to the underlying list. - * @param n The number of elements to pop. - * @return The keys of the popped elements. - */ - function popN(List storage list, uint256 n) internal returns (bytes32[] memory) { - require(n <= list.list.numElements, "not enough elements"); - bytes32[] memory keys = new bytes32[](n); - for (uint256 i = 0; i < n; i = i.add(1)) { - bytes32 key = list.list.head; - keys[i] = key; - remove(list, key); - } - return keys; - } - - /** - * @notice Returns whether or not a particular key is present in the sorted list. - * @param list A storage pointer to the underlying list. - * @param key The element key. - * @return Whether or not the key is in the sorted list. - */ - function contains(List storage list, bytes32 key) internal view returns (bool) { - return list.list.contains(key); - } - - /** - * @notice Returns the value for a particular key in the sorted list. - * @param list A storage pointer to the underlying list. - * @param key The element key. - * @return The element value. - */ - function getValue(List storage list, bytes32 key) internal view returns (uint256) { - return list.values[key]; - } - - /** - * @notice Gets all elements from the doubly linked list. - * @param list A storage pointer to the underlying list. - * @return Array of all keys in the list. - * @return Values corresponding to keys, which will be ordered largest to smallest. - */ - function getElements(List storage list) - internal - view - returns (bytes32[] memory, uint256[] memory) - { - bytes32[] memory keys = getKeys(list); - uint256[] memory values = new uint256[](keys.length); - for (uint256 i = 0; i < keys.length; i = i.add(1)) { - values[i] = list.values[keys[i]]; - } - return (keys, values); - } - - /** - * @notice Gets all element keys from the doubly linked list. - * @param list A storage pointer to the underlying list. - * @return All element keys from head to tail. - */ - function getKeys(List storage list) internal view returns (bytes32[] memory) { - return list.list.getKeys(); - } - - /** - * @notice Returns first N greatest elements of the list. - * @param list A storage pointer to the underlying list. - * @param n The number of elements to return. - * @return The keys of the first n elements. - * @dev Reverts if n is greater than the number of elements in the list. - */ - function headN(List storage list, uint256 n) internal view returns (bytes32[] memory) { - return list.list.headN(n); - } - - /** - * @notice Returns the keys of the elements greaterKey than and less than the provided value. - * @param list A storage pointer to the underlying list. - * @param value The element value. - * @param lesserKey The key of the element which could be just left of the new value. - * @param greaterKey The key of the element which could be just right of the new value. - * @return The correct lesserKey keys. - * @return The correct greaterKey keys. - */ - function getLesserAndGreater( - List storage list, - uint256 value, - bytes32 lesserKey, - bytes32 greaterKey - ) private view returns (bytes32, bytes32) { - // Check for one of the following conditions and fail if none are met: - // 1. The value is less than the current lowest value - // 2. The value is greater than the current greatest value - // 3. The value is just greater than the value for `lesserKey` - // 4. The value is just less than the value for `greaterKey` - if (lesserKey == bytes32(0) && isValueBetween(list, value, lesserKey, list.list.tail)) { - return (lesserKey, list.list.tail); - } else if ( - greaterKey == bytes32(0) && isValueBetween(list, value, list.list.head, greaterKey) - ) { - return (list.list.head, greaterKey); - } else if ( - lesserKey != bytes32(0) && - isValueBetween(list, value, lesserKey, list.list.elements[lesserKey].nextKey) - ) { - return (lesserKey, list.list.elements[lesserKey].nextKey); - } else if ( - greaterKey != bytes32(0) && - isValueBetween(list, value, list.list.elements[greaterKey].previousKey, greaterKey) - ) { - return (list.list.elements[greaterKey].previousKey, greaterKey); - } else { - require(false, "get lesser and greater failure"); - } - } - - /** - * @notice Returns whether or not a given element is between two other elements. - * @param list A storage pointer to the underlying list. - * @param value The element value. - * @param lesserKey The key of the element whose value should be lesserKey. - * @param greaterKey The key of the element whose value should be greaterKey. - * @return True if the given element is between the two other elements. - */ - function isValueBetween(List storage list, uint256 value, bytes32 lesserKey, bytes32 greaterKey) - private - view - returns (bool) - { - bool isLesser = lesserKey == bytes32(0) || list.values[lesserKey] <= value; - bool isGreater = greaterKey == bytes32(0) || list.values[greaterKey] >= value; - return isLesser && isGreater; - } -} diff --git a/packages/protocol/contracts/common/linkedlists/SortedLinkedListWithMedian.sol b/packages/protocol/contracts/common/linkedlists/SortedLinkedListWithMedian.sol deleted file mode 100644 index f7bf9414c..000000000 --- a/packages/protocol/contracts/common/linkedlists/SortedLinkedListWithMedian.sol +++ /dev/null @@ -1,266 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "./LinkedList.sol"; -import "./SortedLinkedList.sol"; - -/** - * @title Maintains a sorted list of unsigned ints keyed by bytes32. - */ -library SortedLinkedListWithMedian { - using SafeMath for uint256; - using SortedLinkedList for SortedLinkedList.List; - - enum MedianAction { None, Lesser, Greater } - - enum MedianRelation { Undefined, Lesser, Greater, Equal } - - struct List { - SortedLinkedList.List list; - bytes32 median; - mapping(bytes32 => MedianRelation) relation; - } - - /** - * @notice Inserts an element into a doubly linked list. - * @param list A storage pointer to the underlying list. - * @param key The key of the element to insert. - * @param value The element value. - * @param lesserKey The key of the element less than the element to insert. - * @param greaterKey The key of the element greater than the element to insert. - */ - function insert( - List storage list, - bytes32 key, - uint256 value, - bytes32 lesserKey, - bytes32 greaterKey - ) internal { - list.list.insert(key, value, lesserKey, greaterKey); - LinkedList.Element storage element = list.list.list.elements[key]; - - MedianAction action = MedianAction.None; - if (list.list.list.numElements == 1) { - list.median = key; - list.relation[key] = MedianRelation.Equal; - } else if (list.list.list.numElements % 2 == 1) { - // When we have an odd number of elements, and the element that we inserted is less than - // the previous median, we need to slide the median down one element, since we had previously - // selected the greater of the two middle elements. - if ( - element.previousKey == bytes32(0) || - list.relation[element.previousKey] == MedianRelation.Lesser - ) { - action = MedianAction.Lesser; - list.relation[key] = MedianRelation.Lesser; - } else { - list.relation[key] = MedianRelation.Greater; - } - } else { - // When we have an even number of elements, and the element that we inserted is greater than - // the previous median, we need to slide the median up one element, since we always select - // the greater of the two middle elements. - if ( - element.nextKey == bytes32(0) || list.relation[element.nextKey] == MedianRelation.Greater - ) { - action = MedianAction.Greater; - list.relation[key] = MedianRelation.Greater; - } else { - list.relation[key] = MedianRelation.Lesser; - } - } - updateMedian(list, action); - } - - /** - * @notice Removes an element from the doubly linked list. - * @param list A storage pointer to the underlying list. - * @param key The key of the element to remove. - */ - function remove(List storage list, bytes32 key) internal { - MedianAction action = MedianAction.None; - if (list.list.list.numElements == 0) { - list.median = bytes32(0); - } else if (list.list.list.numElements % 2 == 0) { - // When we have an even number of elements, we always choose the higher of the two medians. - // Thus, if the element we're removing is greaterKey than or equal to the median we need to - // slide the median left by one. - if ( - list.relation[key] == MedianRelation.Greater || list.relation[key] == MedianRelation.Equal - ) { - action = MedianAction.Lesser; - } - } else { - // When we don't have an even number of elements, we just choose the median value. - // Thus, if the element we're removing is less than or equal to the median, we need to slide - // median right by one. - if ( - list.relation[key] == MedianRelation.Lesser || list.relation[key] == MedianRelation.Equal - ) { - action = MedianAction.Greater; - } - } - updateMedian(list, action); - - list.list.remove(key); - } - - /** - * @notice Updates an element in the list. - * @param list A storage pointer to the underlying list. - * @param key The element key. - * @param value The element value. - * @param lesserKey The key of the element will be just left of `key` after the update. - * @param greaterKey The key of the element will be just right of `key` after the update. - * @dev Note that only one of "lesserKey" or "greaterKey" needs to be correct to reduce friction. - */ - function update( - List storage list, - bytes32 key, - uint256 value, - bytes32 lesserKey, - bytes32 greaterKey - ) internal { - remove(list, key); - insert(list, key, value, lesserKey, greaterKey); - } - - /** - * @notice Inserts an element at the tail of the doubly linked list. - * @param list A storage pointer to the underlying list. - * @param key The key of the element to insert. - */ - function push(List storage list, bytes32 key) internal { - insert(list, key, 0, bytes32(0), list.list.list.tail); - } - - /** - * @notice Removes N elements from the head of the list and returns their keys. - * @param list A storage pointer to the underlying list. - * @param n The number of elements to pop. - * @return The keys of the popped elements. - */ - function popN(List storage list, uint256 n) internal returns (bytes32[] memory) { - require(n <= list.list.list.numElements, "not enough elements"); - bytes32[] memory keys = new bytes32[](n); - for (uint256 i = 0; i < n; i = i.add(1)) { - bytes32 key = list.list.list.head; - keys[i] = key; - remove(list, key); - } - return keys; - } - - /** - * @notice Returns whether or not a particular key is present in the sorted list. - * @param list A storage pointer to the underlying list. - * @param key The element key. - * @return Whether or not the key is in the sorted list. - */ - function contains(List storage list, bytes32 key) internal view returns (bool) { - return list.list.contains(key); - } - - /** - * @notice Returns the value for a particular key in the sorted list. - * @param list A storage pointer to the underlying list. - * @param key The element key. - * @return The element value. - */ - function getValue(List storage list, bytes32 key) internal view returns (uint256) { - return list.list.values[key]; - } - - /** - * @notice Returns the median value of the sorted list. - * @param list A storage pointer to the underlying list. - * @return The median value. - */ - function getMedianValue(List storage list) internal view returns (uint256) { - return getValue(list, list.median); - } - - /** - * @notice Returns the key of the first element in the list. - * @param list A storage pointer to the underlying list. - * @return The key of the first element in the list. - */ - function getHead(List storage list) internal view returns (bytes32) { - return list.list.list.head; - } - - /** - * @notice Returns the key of the median element in the list. - * @param list A storage pointer to the underlying list. - * @return The key of the median element in the list. - */ - function getMedian(List storage list) internal view returns (bytes32) { - return list.median; - } - - /** - * @notice Returns the key of the last element in the list. - * @param list A storage pointer to the underlying list. - * @return The key of the last element in the list. - */ - function getTail(List storage list) internal view returns (bytes32) { - return list.list.list.tail; - } - - /** - * @notice Returns the number of elements in the list. - * @param list A storage pointer to the underlying list. - * @return The number of elements in the list. - */ - function getNumElements(List storage list) internal view returns (uint256) { - return list.list.list.numElements; - } - - /** - * @notice Gets all elements from the doubly linked list. - * @param list A storage pointer to the underlying list. - * @return Array of all keys in the list. - * @return Values corresponding to keys, which will be ordered largest to smallest. - * @return Array of relations to median of corresponding list elements. - */ - function getElements(List storage list) - internal - view - returns (bytes32[] memory, uint256[] memory, MedianRelation[] memory) - { - bytes32[] memory keys = getKeys(list); - uint256[] memory values = new uint256[](keys.length); - MedianRelation[] memory relations = new MedianRelation[](keys.length); - for (uint256 i = 0; i < keys.length; i = i.add(1)) { - values[i] = list.list.values[keys[i]]; - relations[i] = list.relation[keys[i]]; - } - return (keys, values, relations); - } - - /** - * @notice Gets all element keys from the doubly linked list. - * @param list A storage pointer to the underlying list. - * @return All element keys from head to tail. - */ - function getKeys(List storage list) internal view returns (bytes32[] memory) { - return list.list.getKeys(); - } - - /** - * @notice Moves the median pointer right or left of its current value. - * @param list A storage pointer to the underlying list. - * @param action Which direction to move the median pointer. - */ - function updateMedian(List storage list, MedianAction action) private { - LinkedList.Element storage previousMedian = list.list.list.elements[list.median]; - if (action == MedianAction.Lesser) { - list.relation[list.median] = MedianRelation.Greater; - list.median = previousMedian.previousKey; - } else if (action == MedianAction.Greater) { - list.relation[list.median] = MedianRelation.Lesser; - list.median = previousMedian.nextKey; - } - list.relation[list.median] = MedianRelation.Equal; - } -} diff --git a/packages/protocol/contracts/common/proxies/AccountsProxy.sol b/packages/protocol/contracts/common/proxies/AccountsProxy.sol deleted file mode 100644 index 70ace1109..000000000 --- a/packages/protocol/contracts/common/proxies/AccountsProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../Proxy.sol"; - -/* solhint-disable-next-line no-empty-blocks */ -contract AccountsProxy is Proxy {} diff --git a/packages/protocol/contracts/common/proxies/FeeCurrencyWhitelistProxy.sol b/packages/protocol/contracts/common/proxies/FeeCurrencyWhitelistProxy.sol deleted file mode 100644 index b8305f3b6..000000000 --- a/packages/protocol/contracts/common/proxies/FeeCurrencyWhitelistProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../Proxy.sol"; - -/* solhint-disable-next-line no-empty-blocks */ -contract FeeCurrencyWhitelistProxy is Proxy {} diff --git a/packages/protocol/contracts/common/proxies/FeeHandlerProxy.sol b/packages/protocol/contracts/common/proxies/FeeHandlerProxy.sol deleted file mode 100644 index 22050951c..000000000 --- a/packages/protocol/contracts/common/proxies/FeeHandlerProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../Proxy.sol"; - -/* solhint-disable-next-line no-empty-blocks */ -contract FeeHandlerProxy is Proxy {} diff --git a/packages/protocol/contracts/common/proxies/FreezerProxy.sol b/packages/protocol/contracts/common/proxies/FreezerProxy.sol deleted file mode 100644 index ccf59866e..000000000 --- a/packages/protocol/contracts/common/proxies/FreezerProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../Proxy.sol"; - -/* solhint-disable-next-line no-empty-blocks */ -contract FreezerProxy is Proxy {} diff --git a/packages/protocol/contracts/common/proxies/GasPriceMinimumProxy.sol b/packages/protocol/contracts/common/proxies/GasPriceMinimumProxy.sol deleted file mode 100644 index 6a8bf5598..000000000 --- a/packages/protocol/contracts/common/proxies/GasPriceMinimumProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../Proxy.sol"; - -/* solhint-disable-next-line no-empty-blocks */ -contract GasPriceMinimumProxy is Proxy {} diff --git a/packages/protocol/contracts/common/proxies/GoldTokenProxy.sol b/packages/protocol/contracts/common/proxies/GoldTokenProxy.sol deleted file mode 100644 index 18b4209f7..000000000 --- a/packages/protocol/contracts/common/proxies/GoldTokenProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../Proxy.sol"; - -/* solhint-disable-next-line no-empty-blocks */ -contract GoldTokenProxy is Proxy {} diff --git a/packages/protocol/contracts/common/proxies/MentoFeeHandlerSellerProxy.sol b/packages/protocol/contracts/common/proxies/MentoFeeHandlerSellerProxy.sol deleted file mode 100644 index 5eb68a585..000000000 --- a/packages/protocol/contracts/common/proxies/MentoFeeHandlerSellerProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../Proxy.sol"; - -/* solhint-disable-next-line no-empty-blocks */ -contract MentoFeeHandlerSellerProxy is Proxy {} diff --git a/packages/protocol/contracts/common/proxies/MetaTransactionWalletDeployerProxy.sol b/packages/protocol/contracts/common/proxies/MetaTransactionWalletDeployerProxy.sol deleted file mode 100644 index 6cbd504b1..000000000 --- a/packages/protocol/contracts/common/proxies/MetaTransactionWalletDeployerProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.3; - -import "../Proxy.sol"; - -/* solhint-disable-next-line no-empty-blocks */ -contract MetaTransactionWalletDeployerProxy is Proxy {} diff --git a/packages/protocol/contracts/common/proxies/MetaTransactionWalletProxy.sol b/packages/protocol/contracts/common/proxies/MetaTransactionWalletProxy.sol deleted file mode 100644 index 919b34401..000000000 --- a/packages/protocol/contracts/common/proxies/MetaTransactionWalletProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.3; - -import "../Proxy.sol"; - -/* solhint-disable-next-line no-empty-blocks */ -contract MetaTransactionWalletProxy is Proxy {} diff --git a/packages/protocol/contracts/common/proxies/RegistryProxy.sol b/packages/protocol/contracts/common/proxies/RegistryProxy.sol deleted file mode 100644 index e8cc5025b..000000000 --- a/packages/protocol/contracts/common/proxies/RegistryProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../Proxy.sol"; - -/* solhint-disable-next-line no-empty-blocks */ -contract RegistryProxy is Proxy {} diff --git a/packages/protocol/contracts/common/proxies/UniswapFeeHandlerSellerProxy.sol b/packages/protocol/contracts/common/proxies/UniswapFeeHandlerSellerProxy.sol deleted file mode 100644 index e31fc3994..000000000 --- a/packages/protocol/contracts/common/proxies/UniswapFeeHandlerSellerProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../Proxy.sol"; - -/* solhint-disable-next-line no-empty-blocks */ -contract UniswapFeeHandlerSellerProxy is Proxy {} diff --git a/packages/protocol/contracts/common/test/AddressSortedLinkedListWithMedianTest.sol b/packages/protocol/contracts/common/test/AddressSortedLinkedListWithMedianTest.sol deleted file mode 100644 index 3ebc9d800..000000000 --- a/packages/protocol/contracts/common/test/AddressSortedLinkedListWithMedianTest.sol +++ /dev/null @@ -1,50 +0,0 @@ -pragma solidity ^0.5.13; - -import "../linkedlists/AddressSortedLinkedListWithMedian.sol"; -import "../linkedlists/SortedLinkedListWithMedian.sol"; - -contract AddressSortedLinkedListWithMedianTest { - using AddressSortedLinkedListWithMedian for SortedLinkedListWithMedian.List; - - SortedLinkedListWithMedian.List private list; - - function insert(address key, uint256 numerator, address lesserKey, address greaterKey) external { - list.insert(key, numerator, lesserKey, greaterKey); - } - - function update(address key, uint256 numerator, address lesserKey, address greaterKey) external { - list.update(key, numerator, lesserKey, greaterKey); - } - - function remove(address key) external { - list.remove(key); - } - - function contains(address key) external view returns (bool) { - return list.contains(key); - } - - function getNumElements() external view returns (uint256) { - return list.getNumElements(); - } - - function getElements() - external - view - returns (address[] memory, uint256[] memory, SortedLinkedListWithMedian.MedianRelation[] memory) - { - return list.getElements(); - } - - function head() external view returns (address) { - return list.getHead(); - } - - function tail() external view returns (address) { - return list.getTail(); - } - - function medianKey() external view returns (address) { - return list.getMedian(); - } -} diff --git a/packages/protocol/contracts/common/test/ExtractFunctionSignatureTest.sol b/packages/protocol/contracts/common/test/ExtractFunctionSignatureTest.sol deleted file mode 100644 index 47e7ef753..000000000 --- a/packages/protocol/contracts/common/test/ExtractFunctionSignatureTest.sol +++ /dev/null @@ -1,10 +0,0 @@ -pragma solidity ^0.5.13; - -import "../ExtractFunctionSignature.sol"; - -contract ExtractFunctionSignatureTest { - // using ExtractFunctionSignature; - function extractFunctionSignature(bytes memory input) public pure returns (bytes4) { - return ExtractFunctionSignature.extractFunctionSignature(input); - } -} diff --git a/packages/protocol/contracts/common/test/FixidityWrapper.sol b/packages/protocol/contracts/common/test/FixidityWrapper.sol deleted file mode 100644 index 93c409d86..000000000 --- a/packages/protocol/contracts/common/test/FixidityWrapper.sol +++ /dev/null @@ -1,53 +0,0 @@ -pragma solidity ^0.5.13; - -import "../FixidityLib.sol"; - -// Fixidity needs a wrapper as it is a library - -contract FixidityWrapper { - using FixidityLib for FixidityLib.Fraction; - - function newFixed(uint256 a) external pure returns (uint256) { - return FixidityLib.newFixed(a).unwrap(); - } - - function newFixedFraction(uint256 a, uint256 b) external pure returns (uint256) { - return FixidityLib.newFixedFraction(a, b).unwrap(); - } - - function add(uint256 a, uint256 b) external pure returns (uint256) { - return FixidityLib.wrap(a).add(FixidityLib.wrap(b)).unwrap(); - } - - function subtract(uint256 a, uint256 b) external pure returns (uint256) { - return FixidityLib.wrap(a).subtract(FixidityLib.wrap(b)).unwrap(); - } - - function multiply(uint256 a, uint256 b) external pure returns (uint256) { - return FixidityLib.wrap(a).multiply(FixidityLib.wrap(b)).unwrap(); - } - - function reciprocal(uint256 a) external pure returns (uint256) { - return FixidityLib.wrap(a).reciprocal().unwrap(); - } - - function divide(uint256 a, uint256 b) external pure returns (uint256) { - return FixidityLib.wrap(a).divide(FixidityLib.wrap(b)).unwrap(); - } - - function gt(uint256 a, uint256 b) external pure returns (bool) { - return FixidityLib.wrap(a).gt(FixidityLib.wrap(b)); - } - - function gte(uint256 a, uint256 b) external pure returns (bool) { - return FixidityLib.wrap(a).gte(FixidityLib.wrap(b)); - } - - function lt(uint256 a, uint256 b) external pure returns (bool) { - return FixidityLib.wrap(a).lt(FixidityLib.wrap(b)); - } - - function lte(uint256 a, uint256 b) external pure returns (bool) { - return FixidityLib.wrap(a).lte(FixidityLib.wrap(b)); - } -} diff --git a/packages/protocol/contracts/common/test/GetSetV0.sol b/packages/protocol/contracts/common/test/GetSetV0.sol deleted file mode 100644 index 17706704c..000000000 --- a/packages/protocol/contracts/common/test/GetSetV0.sol +++ /dev/null @@ -1,13 +0,0 @@ -pragma solidity ^0.5.13; - -contract GetSetV0 { - uint256 public x; - - function get() external view returns (uint256) { - return x; - } - - function set(uint256 _x) external { - x = _x; - } -} diff --git a/packages/protocol/contracts/common/test/GetSetV1.sol b/packages/protocol/contracts/common/test/GetSetV1.sol deleted file mode 100644 index f9787c3f8..000000000 --- a/packages/protocol/contracts/common/test/GetSetV1.sol +++ /dev/null @@ -1,15 +0,0 @@ -pragma solidity ^0.5.13; - -contract GetSetV1 { - uint256 public x; - string public y; - - function get() external view returns (uint256, string memory) { - return (x, y); - } - - function set(uint256 _x, string calldata _y) external { - x = _x; - y = _y; - } -} diff --git a/packages/protocol/contracts/common/test/HasInitializer.sol b/packages/protocol/contracts/common/test/HasInitializer.sol deleted file mode 100644 index f07e6938f..000000000 --- a/packages/protocol/contracts/common/test/HasInitializer.sol +++ /dev/null @@ -1,11 +0,0 @@ -pragma solidity ^0.5.13; - -import "../Initializable.sol"; - -contract HasInitializer is Initializable(true) { - uint256 public x; - - function initialize(uint256 _x) external initializer { - x = _x; - } -} diff --git a/packages/protocol/contracts/common/test/IntegerSortedLinkedListTest.sol b/packages/protocol/contracts/common/test/IntegerSortedLinkedListTest.sol deleted file mode 100644 index 13c71d92b..000000000 --- a/packages/protocol/contracts/common/test/IntegerSortedLinkedListTest.sol +++ /dev/null @@ -1,45 +0,0 @@ -pragma solidity ^0.5.13; - -import "../linkedlists/IntegerSortedLinkedList.sol"; - -contract IntegerSortedLinkedListTest { - using IntegerSortedLinkedList for SortedLinkedList.List; - - SortedLinkedList.List private list; - - function insert(uint256 key, uint256 value, uint256 lesserKey, uint256 greaterKey) external { - list.insert(key, value, lesserKey, greaterKey); - } - - function update(uint256 key, uint256 value, uint256 lesserKey, uint256 greaterKey) external { - list.update(key, value, lesserKey, greaterKey); - } - - function remove(uint256 key) external { - list.remove(key); - } - - function popN(uint256 n) external returns (uint256[] memory) { - return list.popN(n); - } - - function contains(uint256 key) external view returns (bool) { - return list.contains(key); - } - - function getNumElements() external view returns (uint256) { - return list.list.numElements; - } - - function getElements() external view returns (uint256[] memory, uint256[] memory) { - return list.getElements(); - } - - function head() external view returns (uint256) { - return uint256(list.list.head); - } - - function tail() external view returns (uint256) { - return uint256(list.list.tail); - } -} diff --git a/packages/protocol/contracts/common/test/LinkedListWrapper.sol b/packages/protocol/contracts/common/test/LinkedListWrapper.sol deleted file mode 100644 index 64087fc00..000000000 --- a/packages/protocol/contracts/common/test/LinkedListWrapper.sol +++ /dev/null @@ -1,42 +0,0 @@ -pragma solidity ^0.5.13; - -import "../linkedlists/LinkedList.sol"; - -contract LinkedListWrapper { - using LinkedList for LinkedList.List; - - LinkedList.List private list; - - function insert(bytes32 key, bytes32 previousKey, bytes32 nextKey) external { - list.insert(key, previousKey, nextKey); - } - - function update(bytes32 key, bytes32 previousKey, bytes32 nextKey) external { - list.update(key, previousKey, nextKey); - } - - function remove(bytes32 key) external { - list.remove(key); - } - - function contains(bytes32 key) external view returns (bool) { - return list.contains(key); - } - - function getNumElements() external view returns (uint256) { - return list.numElements; - } - - function getKeys() external view returns (bytes32[] memory) { - return list.getKeys(); - } - - function head() external view returns (bytes32) { - return list.head; - } - - function tail() external view returns (bytes32) { - return list.tail; - } - -} diff --git a/packages/protocol/contracts/common/test/MockGoldToken.sol b/packages/protocol/contracts/common/test/MockGoldToken.sol deleted file mode 100644 index 8795d8ebc..000000000 --- a/packages/protocol/contracts/common/test/MockGoldToken.sol +++ /dev/null @@ -1,42 +0,0 @@ -pragma solidity ^0.5.13; -// solhint-disable no-unused-vars - -import "../GoldToken.sol"; - -/** - * @title A mock GoldToken for testing. - */ -contract MockGoldToken is GoldToken(true) { - uint8 public constant decimals = 18; - mapping(address => uint256) balances; - - function setTotalSupply(uint256 value) external { - totalSupply_ = value; - } - - function transfer(address to, uint256 amount) external returns (bool) { - return _transfer(msg.sender, to, amount); - } - - function transferFrom(address from, address to, uint256 amount) external returns (bool) { - return _transfer(from, to, amount); - } - - function _transfer(address from, address to, uint256 amount) internal returns (bool) { - if (balances[from] < amount) { - return false; - } - balances[from] -= amount; - balances[to] += amount; - return true; - } - - function setBalanceOf(address a, uint256 value) external { - balances[a] = value; - } - - function balanceOf(address a) public view returns (uint256) { - return balances[a]; - } - -} diff --git a/packages/protocol/contracts/common/test/MsgSenderCheck.sol b/packages/protocol/contracts/common/test/MsgSenderCheck.sol deleted file mode 100644 index 6ff9fae3f..000000000 --- a/packages/protocol/contracts/common/test/MsgSenderCheck.sol +++ /dev/null @@ -1,7 +0,0 @@ -pragma solidity ^0.5.13; - -contract MsgSenderCheck { - function checkMsgSender(address addr) external view { - require(addr == msg.sender, "address was not msg.sender"); - } -} diff --git a/packages/protocol/contracts/governance/BlockchainParameters.sol b/packages/protocol/contracts/governance/BlockchainParameters.sol deleted file mode 100644 index 49b9d421b..000000000 --- a/packages/protocol/contracts/governance/BlockchainParameters.sol +++ /dev/null @@ -1,129 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; -import "../common/Initializable.sol"; -import "../common/UsingPrecompiles.sol"; - -/** - * @title Contract for storing blockchain parameters that can be set by governance. - */ -contract BlockchainParameters is Ownable, Initializable, UsingPrecompiles { - using SafeMath for uint256; - - // obsolete - struct ClientVersion { - uint256 major; - uint256 minor; - uint256 patch; - } - - struct LookbackWindow { - // Value for lookbackWindow before `nextValueActivationBlock` - uint256 oldValue; - // Value for lookbackWindow after `nextValueActivationBlock` - uint256 nextValue; - // Epoch where next value is activated - uint256 nextValueActivationEpoch; - } - - ClientVersion private minimumClientVersion; // obsolete - uint256 public blockGasLimit; - uint256 public intrinsicGasForAlternativeFeeCurrency; - LookbackWindow public uptimeLookbackWindow; - - event IntrinsicGasForAlternativeFeeCurrencySet(uint256 gas); - event BlockGasLimitSet(uint256 limit); - event UptimeLookbackWindowSet(uint256 window, uint256 activationEpoch); - - /** - * @notice Sets initialized == true on implementation contracts - * @param test Set to true to skip implementation initialization - */ - constructor(bool test) public Initializable(test) {} - - /** - * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. - * @param _gasForNonGoldCurrencies Intrinsic gas for non-gold gas currencies. - * @param gasLimit Block gas limit. - * @param lookbackWindow Lookback window for measuring validator uptime. - */ - function initialize(uint256 _gasForNonGoldCurrencies, uint256 gasLimit, uint256 lookbackWindow) - external - initializer - { - _transferOwnership(msg.sender); - setBlockGasLimit(gasLimit); - setIntrinsicGasForAlternativeFeeCurrency(_gasForNonGoldCurrencies); - setUptimeLookbackWindow(lookbackWindow); - } - - /** - * @notice Returns the storage, major, minor, and patch version of the contract. - * @return Storage version of the contract. - * @return Major version of the contract. - * @return Minor version of the contract. - * @return Patch version of the contract. - */ - function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { - return (1, 3, 0, 0); - } - - /** - * @notice Sets the block gas limit. - * @param gasLimit New block gas limit. - */ - function setBlockGasLimit(uint256 gasLimit) public onlyOwner { - blockGasLimit = gasLimit; - emit BlockGasLimitSet(gasLimit); - } - - /** - * @notice Sets the intrinsic gas for non-gold gas currencies. - * @param gas Intrinsic gas for non-gold gas currencies. - */ - function setIntrinsicGasForAlternativeFeeCurrency(uint256 gas) public onlyOwner { - intrinsicGasForAlternativeFeeCurrency = gas; - emit IntrinsicGasForAlternativeFeeCurrencySet(gas); - } - - /** - * @notice Sets the uptime lookback window. - * @param window New window. - */ - function setUptimeLookbackWindow(uint256 window) public onlyOwner { - require(window >= 3 && window <= 720, "UptimeLookbackWindow must be within safe range"); - require( - window <= getEpochSize().sub(2), - "UptimeLookbackWindow must be smaller or equal to epochSize - 2" - ); - - uptimeLookbackWindow.oldValue = _getUptimeLookbackWindow(); - - // changes only take place on the next epoch - uptimeLookbackWindow.nextValueActivationEpoch = getEpochNumber().add(1); - uptimeLookbackWindow.nextValue = window; - - emit UptimeLookbackWindowSet(window, uptimeLookbackWindow.nextValueActivationEpoch); - } - - /** - * @notice Gets the uptime lookback window. - */ - function getUptimeLookbackWindow() public view returns (uint256 lookbackWindow) { - lookbackWindow = _getUptimeLookbackWindow(); - require(lookbackWindow != 0, "UptimeLookbackWindow is not initialized"); - } - - /** - * @notice Gets the uptime lookback window. - */ - function _getUptimeLookbackWindow() internal view returns (uint256 lookbackWindow) { - if (getEpochNumber() >= uptimeLookbackWindow.nextValueActivationEpoch) { - return uptimeLookbackWindow.nextValue; - } else { - return uptimeLookbackWindow.oldValue; - } - } - -} diff --git a/packages/protocol/contracts/governance/DoubleSigningSlasher.sol b/packages/protocol/contracts/governance/DoubleSigningSlasher.sol deleted file mode 100644 index cf2cd93b6..000000000 --- a/packages/protocol/contracts/governance/DoubleSigningSlasher.sol +++ /dev/null @@ -1,164 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "../common/interfaces/ICeloVersionedContract.sol"; - -import "./SlasherUtil.sol"; - -contract DoubleSigningSlasher is ICeloVersionedContract, SlasherUtil { - using SafeMath for uint256; - - // For each signer address, check if a block header has already been slashed - mapping(address => mapping(bytes32 => bool)) isSlashed; - - event SlashingIncentivesSet(uint256 penalty, uint256 reward); - event DoubleSigningSlashPerformed(address indexed validator, uint256 indexed blockNumber); - - /** - * @notice Returns the storage, major, minor, and patch version of the contract. - * @return Storage version of the contract. - * @return Major version of the contract. - * @return Minor version of the contract. - * @return Patch version of the contract. - */ - function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { - return (1, 1, 1, 0); - } - - /** - * @notice Sets initialized == true on implementation contracts - * @param test Set to true to skip implementation initialization - */ - constructor(bool test) public SlasherUtil(test) {} - - /** - * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. - * @param registryAddress The address of the registry core smart contract. - * @param _penalty Penalty for the slashed signer. - * @param _reward Reward that the observer gets. - */ - function initialize(address registryAddress, uint256 _penalty, uint256 _reward) - external - initializer - { - _transferOwnership(msg.sender); - setRegistry(registryAddress); - setSlashingIncentives(_penalty, _reward); - } - - /** - * @notice Counts the number of set bits (Hamming weight). - * @param v Bitmap. - * @return Number of set bits. - */ - function countSetBits(uint256 v) internal pure returns (uint256) { - uint256 res = 0; - uint256 acc = v; - for (uint256 i = 0; i < 256; i = i.add(1)) { - if (acc & 1 == 1) res = res.add(1); - acc = acc >> 1; - } - return res; - } - - /** - * @notice Given two RLP encoded blocks, calls into precompiles to require that - * the two block hashes are different, have the same height, have a - * quorum of signatures, and that `signer` was part of the quorum. - * @param signer The signer to be slashed. - * @param index Validator index at the block. - * @param headerA First double signed block header. - * @param headerB Second double signed block header. - * @return Block number where double signing occured. Throws if no double signing is detected. - */ - function checkForDoubleSigning( - address signer, - uint256 index, - bytes memory headerA, - bytes memory headerB - ) public view returns (uint256) { - require(hashHeader(headerA) != hashHeader(headerB), "Block hashes have to be different"); - uint256 blockNumber = getBlockNumberFromHeader(headerA); - require( - blockNumber == getBlockNumberFromHeader(headerB), - "Block headers are from different height" - ); - require(index < numberValidatorsInSet(blockNumber), "Bad validator index"); - require( - signer == validatorSignerAddressFromSet(index, blockNumber), - "Wasn't a signer with given index" - ); - uint256 mapA = uint256(getVerifiedSealBitmapFromHeader(headerA)); - uint256 mapB = uint256(getVerifiedSealBitmapFromHeader(headerB)); - require(mapA & (1 << index) != 0, "Didn't sign first block"); - require(mapB & (1 << index) != 0, "Didn't sign second block"); - require( - countSetBits(mapA) >= minQuorumSize(blockNumber), - "Not enough signers in the first block" - ); - require( - countSetBits(mapB) >= minQuorumSize(blockNumber), - "Not enough signers in the second block" - ); - return blockNumber; - } - - function checkIfAlreadySlashed(address signer, bytes memory header) internal { - bytes32 bhash = hashHeader(header); - require(!isSlashed[signer][bhash], "Already slashed"); - isSlashed[signer][bhash] = true; - } - - /** - * @notice Requires that `eval` returns true and that this evidence has not - * already been used to slash `signer`. - * If so, fetches the `account` associated with `signer` and the group that - * `signer` was a member of during the corresponding epoch. - * Then, calls `LockedGold.slash` on both the validator and group accounts. - * Calls `Validators.removeSlashedMember` to remove the validator from its - * current group if it is a member of one. - * Finally, stores that hash(signer, blockNumber) has been slashed. - * @param signer The signer to be slashed. - * @param index Validator index at the block. - * @param headerA First double signed block header. - * @param headerB Second double signed block header. - * @param groupMembershipHistoryIndex Group membership index from where the group should be found. - * @param validatorElectionLessers Lesser pointers for validator slashing. - * @param validatorElectionGreaters Greater pointers for validator slashing. - * @param validatorElectionIndices Vote indices for validator slashing. - * @param groupElectionLessers Lesser pointers for group slashing. - * @param groupElectionGreaters Greater pointers for group slashing. - * @param groupElectionIndices Vote indices for group slashing. - */ - function slash( - address signer, - uint256 index, - bytes memory headerA, - bytes memory headerB, - uint256 groupMembershipHistoryIndex, - address[] memory validatorElectionLessers, - address[] memory validatorElectionGreaters, - uint256[] memory validatorElectionIndices, - address[] memory groupElectionLessers, - address[] memory groupElectionGreaters, - uint256[] memory groupElectionIndices - ) public { - checkIfAlreadySlashed(signer, headerA); - checkIfAlreadySlashed(signer, headerB); - uint256 blockNumber = checkForDoubleSigning(signer, index, headerA, headerB); - address validator = getAccounts().signerToAccount(signer); - performSlashing( - validator, - msg.sender, - blockNumber, - groupMembershipHistoryIndex, - validatorElectionLessers, - validatorElectionGreaters, - validatorElectionIndices, - groupElectionLessers, - groupElectionGreaters, - groupElectionIndices - ); - emit DoubleSigningSlashPerformed(validator, blockNumber); - } -} diff --git a/packages/protocol/contracts/governance/DowntimeSlasher.sol b/packages/protocol/contracts/governance/DowntimeSlasher.sol deleted file mode 100644 index 6e5480d8f..000000000 --- a/packages/protocol/contracts/governance/DowntimeSlasher.sol +++ /dev/null @@ -1,316 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; - -import "./SlasherUtil.sol"; -import "../common/interfaces/ICeloVersionedContract.sol"; - -contract DowntimeSlasher is ICeloVersionedContract, SlasherUtil { - using SafeMath for uint256; - - // Maps validator address -> end block of the latest interval for which it has been slashed. - mapping(address => uint256) public lastSlashedBlock; - - // Maps user address -> startBlock -> endBlock -> signature bitmap for that interval. - // Note that startBlock and endBlock must always be in the same epoch. - mapping(address => mapping(uint256 => mapping(uint256 => bytes32))) public bitmaps; - - uint256 public slashableDowntime; - - event SlashableDowntimeSet(uint256 interval); - event DowntimeSlashPerformed( - address indexed validator, - uint256 indexed startBlock, - uint256 indexed endBlock - ); - event BitmapSetForInterval( - address indexed sender, - uint256 indexed startBlock, - uint256 indexed endBlock, - bytes32 bitmap - ); - - /** - * @notice Returns the storage, major, minor, and patch version of the contract. - * @return Storage version of the contract. - * @return Major version of the contract. - * @return Minor version of the contract. - * @return Patch version of the contract. - */ - function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { - return (2, 0, 0, 0); - } - - /** - * @notice Sets initialized == true on implementation contracts - * @param test Set to true to skip implementation initialization - */ - constructor(bool test) public SlasherUtil(test) {} - - /** - * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. - * @param registryAddress The address of the registry core smart contract. - * @param _penalty Penalty for the slashed validator. - * @param _reward Reward that the observer gets. - * @param _slashableDowntime Slashable downtime in blocks. - */ - function initialize( - address registryAddress, - uint256 _penalty, - uint256 _reward, - uint256 _slashableDowntime - ) external initializer { - _transferOwnership(msg.sender); - setRegistry(registryAddress); - setSlashingIncentives(_penalty, _reward); - setSlashableDowntime(_slashableDowntime); - } - - /** - * @notice Sets the slashable downtime. - * @param interval Slashable downtime in blocks. - */ - function setSlashableDowntime(uint256 interval) public onlyOwner { - require(interval != 0, "slashable downtime cannot be zero"); - slashableDowntime = interval; - emit SlashableDowntimeSet(interval); - } - - /** - * @notice Calculates and returns the signature bitmap for the specified interval. - * This bitmap will contain a one for any validator that signed at least one block in that - * interval, and zero otherwise. - * @param startBlock First block of the interval. - * @param endBlock Last block of the interval. - * @return The signature uptime bitmap for the specified interval. - * @dev startBlock and endBlock must be in the same epoch. - * @dev The getParentSealBitmap precompile requires that startBlock must be within 4 epochs of - * the current block. - */ - function getBitmapForInterval(uint256 startBlock, uint256 endBlock) - public - view - returns (bytes32) - { - require(endBlock >= startBlock, "endBlock must be greater or equal than startBlock"); - // The signature bitmap for block N is stored in block N+1. - // The latest block is `block.number - 1`, which stores the signature bitmap for - // `block.number - 2`. - uint256 lastBlockWithSignatureBitmap = block.number.sub(2); - require( - endBlock <= lastBlockWithSignatureBitmap, - "the signature bitmap for endBlock is not yet available" - ); - uint256 epochSize = getEpochSize(); - require( - block.number.sub(startBlock) < epochSize.mul(4), - "startBlock must be within 4 epochs of the current head" - ); - require( - epochNumberOfBlock(startBlock, epochSize) == epochNumberOfBlock(endBlock, epochSize), - "startBlock and endBlock must be in the same epoch" - ); - - bytes32 bitmap; - for ( - uint256 blockNumber = startBlock; - blockNumber <= endBlock; - blockNumber = blockNumber.add(1) - ) { - // The canonical signatures for block N are stored in the parent seal bitmap for block N+1. - bitmap |= getParentSealBitmap(blockNumber.add(1)); - } - - return bitmap; - } - - /** - * @notice Calculates and sets the signature bitmap for the specified interval. - * @param startBlock First block of the interval. - * @param endBlock Last block of the interval. - * @return The signature bitmap for the specified interval. - * @dev startBlock and endBlock must be in the same epoch. - */ - function setBitmapForInterval(uint256 startBlock, uint256 endBlock) public returns (bytes32) { - require(!isBitmapSetForInterval(startBlock, endBlock), "bitmap already set"); - - bytes32 bitmap = getBitmapForInterval(startBlock, endBlock); - bitmaps[msg.sender][startBlock][endBlock] = bitmap; - - emit BitmapSetForInterval(msg.sender, startBlock, endBlock, bitmap); - - return bitmap; - } - - /** - * @notice Returns true if the validator did not sign any blocks in the specified interval. - * @param startBlock First block of the interval. - * @param endBlock Last block of the interval. - * @param signerIndex Index of the signer within the validator set. - * @return True if the validator did not sign any blocks in the specified interval. - * @dev Both startBlock and endBlock should be part of the same epoch. - */ - function wasDownForInterval(uint256 startBlock, uint256 endBlock, uint256 signerIndex) - public - view - returns (bool) - { - require(signerIndex < numberValidatorsInSet(startBlock), "bad validator index at start block"); - require( - isBitmapSetForInterval(startBlock, endBlock), - "bitmap for specified interval not yet set" - ); - - return (bitmaps[msg.sender][startBlock][endBlock] & bytes32(1 << signerIndex)) == 0; - } - - /** - * @notice Returns true if the bitmap has been set for the specified interval. - * @param startBlock First block of the interval. - * @param endBlock Last block of the interval. - * @return True if the bitmap has been set for the specified interval. - */ - function isBitmapSetForInterval(uint256 startBlock, uint256 endBlock) public view returns (bool) { - // It's impossible to have all the validators down in an interval. - return bitmaps[msg.sender][startBlock][endBlock] != 0; - } - - /** - * @notice Returns true if a validator has been down for the specified overlapping or adjacent - * intervals. - * @param startBlocks A list of interval start blocks for which signature bitmaps have already - * been set. - * @param endBlocks A list of interval end blocks for which signature bitmaps have already - * been set. - * @param signerIndices Indices of the signer within the validator set for every epoch change. - * @return True if the validator signature does not appear in any block within the window. - */ - function wasDownForIntervals( - uint256[] memory startBlocks, - uint256[] memory endBlocks, - uint256[] memory signerIndices - ) public view returns (bool) { - require(startBlocks.length > 0, "requires at least one interval"); - require( - startBlocks.length == endBlocks.length, - "startBlocks and endBlocks must have the same length" - ); - require(signerIndices.length > 0, "requires at least one signerIndex"); - - uint256 epochSize = getEpochSize(); - uint256 signerIndicesIndex = 0; - for (uint256 i = 0; i < startBlocks.length; i = i.add(1)) { - if (i > 0) { - require( - startBlocks[i.sub(1)] < startBlocks[i], - "each interval must start after the start of the previous interval" - ); - require( - startBlocks[i] <= endBlocks[i.sub(1)].add(1), - "each interval must start at most one block after the end of the previous interval" - ); - require( - endBlocks[i.sub(1)] < endBlocks[i], - "each interval must end after the end of the previous interval" - ); - // The signer index of a particular validator may change from epoch to epoch. - // Because the intervals for which bitmaps are calculated in this contract do not span - // epochs, and because intervals processed by this function are guaranteed to be - // overlapping or contiguous, whenever we cross epoch boundaries we are guaranteed to - // process an interval that starts with the first block of that epoch. - if (startBlocks[i].mod(epochSize) == 1) { - require( - getValidatorAccountFromSignerIndex( - signerIndices[signerIndicesIndex], - startBlocks[i].sub(1) - ) == - getValidatorAccountFromSignerIndex( - signerIndices[signerIndicesIndex.add(1)], - startBlocks[i] - ), - "indices do not point to the same validator" - ); - signerIndicesIndex = signerIndicesIndex.add(1); - } - } - if (!wasDownForInterval(startBlocks[i], endBlocks[i], signerIndices[signerIndicesIndex])) { - return false; - } - } - - return true; - } - - /** - * @notice Slashes a validator that did not sign any blocks for at least `slashableDowntime`. - * @param startBlocks A list of interval start blocks for which signature bitmaps have already - * been set. - * @param endBlocks A list of interval end blocks for which signature bitmaps have already - * been set. - * @param signerIndices The index of the provided validator for each epoch over which the - * provided intervals span. - * @param groupMembershipHistoryIndex Group membership index from where - * the group should be found (For start block). - * @param validatorElectionLessers Lesser pointers for validator slashing. - * @param validatorElectionGreaters Greater pointers for validator slashing. - * @param validatorElectionIndices Vote indices for validator slashing. - * @param groupElectionLessers Lesser pointers for group slashing. - * @param groupElectionGreaters Greater pointers for group slashing. - * @param groupElectionIndices Vote indices for group slashing. - * @dev startBlocks[0] will be use as the startBlock of the slashableDowntime. - */ - function slash( - uint256[] memory startBlocks, - uint256[] memory endBlocks, - uint256[] memory signerIndices, - uint256 groupMembershipHistoryIndex, - address[] memory validatorElectionLessers, - address[] memory validatorElectionGreaters, - uint256[] memory validatorElectionIndices, - address[] memory groupElectionLessers, - address[] memory groupElectionGreaters, - uint256[] memory groupElectionIndices - ) public { - uint256 startBlock = startBlocks[0]; - uint256 endBlock = endBlocks[endBlocks.length.sub(1)]; - require( - endBlock.sub(startBlock).add(1) >= slashableDowntime, - "the provided intervals must span slashableDowntime blocks" - ); - address validator = getValidatorAccountFromSignerIndex(signerIndices[0], startBlock); - require( - startBlock > lastSlashedBlock[validator], - "cannot slash validator for downtime for which they may already have been slashed" - ); - require(wasDownForIntervals(startBlocks, endBlocks, signerIndices), "not down"); - lastSlashedBlock[validator] = endBlock; - performSlashing( - validator, - msg.sender, - startBlock, - groupMembershipHistoryIndex, - validatorElectionLessers, - validatorElectionGreaters, - validatorElectionIndices, - groupElectionLessers, - groupElectionGreaters, - groupElectionIndices - ); - emit DowntimeSlashPerformed(validator, startBlock, endBlock); - } - - /** - * @notice Returns the validator's address of the signer for a specific block number. - * @param signerIndex Index of the signer within the validator set for a specific epoch. - * @param blockNumber Block number where the validator was elected. - * @return Validator's address. - */ - function getValidatorAccountFromSignerIndex(uint256 signerIndex, uint256 blockNumber) - internal - view - returns (address) - { - return getAccounts().signerToAccount(validatorSignerAddressFromSet(signerIndex, blockNumber)); - } -} diff --git a/packages/protocol/contracts/governance/Election.sol b/packages/protocol/contracts/governance/Election.sol deleted file mode 100644 index c984dcf7d..000000000 --- a/packages/protocol/contracts/governance/Election.sol +++ /dev/null @@ -1,1181 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/Math.sol"; -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./interfaces/IElection.sol"; -import "./interfaces/IValidators.sol"; -import "../common/CalledByVm.sol"; -import "../common/Initializable.sol"; -import "../common/FixidityLib.sol"; -import "../common/linkedlists/AddressSortedLinkedList.sol"; -import "../common/UsingPrecompiles.sol"; -import "../common/UsingRegistry.sol"; -import "../common/interfaces/ICeloVersionedContract.sol"; -import "../common/libraries/Heap.sol"; -import "../common/libraries/ReentrancyGuard.sol"; - -contract Election is - IElection, - ICeloVersionedContract, - Ownable, - ReentrancyGuard, - Initializable, - UsingRegistry, - UsingPrecompiles, - CalledByVm -{ - using AddressSortedLinkedList for SortedLinkedList.List; - using FixidityLib for FixidityLib.Fraction; - using SafeMath for uint256; - - // 1e20 ensures that units can be represented as precisely as possible to avoid rounding errors - // when translating to votes, without risking integer overflow. - // A maximum of 1,000,000,000 CELO (1e27) yields a maximum of 1e47 units, whose product is at - // most 1e74, which is less than 2^256. - uint256 private constant UNIT_PRECISION_FACTOR = 100000000000000000000; - - struct PendingVote { - // The value of the vote, in gold. - uint256 value; - // The epoch at which the vote was cast. - uint256 epoch; - } - - struct GroupPendingVotes { - // The total number of pending votes that have been cast for this group. - uint256 total; - // Pending votes cast per voter. - mapping(address => PendingVote) byAccount; - } - - // Pending votes are those for which no following elections have been held. - // These votes have yet to contribute to the election of validators and thus do not accrue - // rewards. - struct PendingVotes { - // The total number of pending votes cast across all groups. - uint256 total; - mapping(address => GroupPendingVotes) forGroup; - } - - struct GroupActiveVotes { - // The total number of active votes that have been cast for this group. - uint256 total; - // The total number of active votes by a voter is equal to the number of active vote units for - // that voter times the total number of active votes divided by the total number of active - // vote units. - uint256 totalUnits; - mapping(address => uint256) unitsByAccount; - } - - // Active votes are those for which at least one following election has been held. - // These votes have contributed to the election of validators and thus accrue rewards. - struct ActiveVotes { - // The total number of active votes cast across all groups. - uint256 total; - mapping(address => GroupActiveVotes) forGroup; - } - - struct TotalVotes { - // A list of eligible ValidatorGroups sorted by total (pending+active) votes. - // Note that this list will omit ineligible ValidatorGroups, including those that may have > 0 - // total votes. - SortedLinkedList.List eligible; - } - - struct Votes { - PendingVotes pending; - ActiveVotes active; - TotalVotes total; - // Maps an account to the list of groups it's voting for. - mapping(address => address[]) groupsVotedFor; - } - - struct ElectableValidators { - uint256 min; - uint256 max; - } - - struct CachedVotes { - // group => votes - mapping(address => uint256) cachedVotesPerGroup; - uint256 totalVotes; - } - - Votes private votes; - // Governs the minimum and maximum number of validators that can be elected. - ElectableValidators public electableValidators; - // Governs how many validator groups a single account can vote for. - uint256 public maxNumGroupsVotedFor; - // Groups must receive at least this fraction of the total votes in order to be considered in - // elections. - FixidityLib.Fraction public electabilityThreshold; - - // If set to true for account, the account is able to vote for more - // than max number of groups voted for. - mapping(address => bool) public allowedToVoteOverMaxNumberOfGroups; - - mapping(address => CachedVotes) public cachedVotesByAccount; - - event ElectableValidatorsSet(uint256 min, uint256 max); - event MaxNumGroupsVotedForSet(uint256 maxNumGroupsVotedFor); - event ElectabilityThresholdSet(uint256 electabilityThreshold); - event AllowedToVoteOverMaxNumberOfGroups(address indexed account, bool flag); - event ValidatorGroupMarkedEligible(address indexed group); - event ValidatorGroupMarkedIneligible(address indexed group); - event ValidatorGroupVoteCast(address indexed account, address indexed group, uint256 value); - event ValidatorGroupVoteActivated( - address indexed account, - address indexed group, - uint256 value, - uint256 units - ); - event ValidatorGroupPendingVoteRevoked( - address indexed account, - address indexed group, - uint256 value - ); - event ValidatorGroupActiveVoteRevoked( - address indexed account, - address indexed group, - uint256 value, - uint256 units - ); - event EpochRewardsDistributedToVoters(address indexed group, uint256 value); - - /** - * @notice Returns the storage, major, minor, and patch version of the contract. - * @return Storage version of the contract. - * @return Major version of the contract. - * @return Minor version of the contract. - * @return Patch version of the contract. - */ - function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { - return (1, 1, 3, 0); - } - - /** - * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. - * @param registryAddress The address of the registry core smart contract. - * @param minElectableValidators The minimum number of validators that can be elected. - * @param _maxNumGroupsVotedFor The maximum number of groups that an account can vote for at once. - * @param _electabilityThreshold The minimum ratio of votes a group needs before its members can - * be elected. - * @dev Should be called only once. - */ - function initialize( - address registryAddress, - uint256 minElectableValidators, - uint256 maxElectableValidators, - uint256 _maxNumGroupsVotedFor, - uint256 _electabilityThreshold - ) external initializer { - _transferOwnership(msg.sender); - setRegistry(registryAddress); - setElectableValidators(minElectableValidators, maxElectableValidators); - setMaxNumGroupsVotedFor(_maxNumGroupsVotedFor); - setElectabilityThreshold(_electabilityThreshold); - } - - /** - * @notice Sets initialized == true on implementation contracts - * @param test Set to true to skip implementation initialization - */ - constructor(bool test) public Initializable(test) {} - - /** - * @notice Updates the minimum and maximum number of validators that can be elected. - * @param min The minimum number of validators that can be elected. - * @param max The maximum number of validators that can be elected. - * @return True upon success. - */ - function setElectableValidators(uint256 min, uint256 max) public onlyOwner returns (bool) { - require(0 < min, "Minimum electable validators cannot be zero"); - require(min <= max, "Maximum electable validators cannot be smaller than minimum"); - require( - min != electableValidators.min || max != electableValidators.max, - "Electable validators not changed" - ); - electableValidators = ElectableValidators(min, max); - emit ElectableValidatorsSet(min, max); - return true; - } - - /** - * @notice Returns the minimum and maximum number of validators that can be elected. - * @return The minimum number of validators that can be elected. - * @return The maximum number of validators that can be elected. - */ - function getElectableValidators() external view returns (uint256, uint256) { - return (electableValidators.min, electableValidators.max); - } - - /** - * @notice Updates the maximum number of groups an account can be voting for at once. - * @param _maxNumGroupsVotedFor The maximum number of groups an account can vote for. - * @return True upon success. - */ - function setMaxNumGroupsVotedFor(uint256 _maxNumGroupsVotedFor) public onlyOwner returns (bool) { - require(_maxNumGroupsVotedFor != maxNumGroupsVotedFor, "Max groups voted for not changed"); - maxNumGroupsVotedFor = _maxNumGroupsVotedFor; - emit MaxNumGroupsVotedForSet(_maxNumGroupsVotedFor); - return true; - } - - /** - * @notice Sets the electability threshold. - * @param threshold Electability threshold as unwrapped Fraction. - * @return True upon success. - */ - function setElectabilityThreshold(uint256 threshold) public onlyOwner returns (bool) { - electabilityThreshold = FixidityLib.wrap(threshold); - require( - electabilityThreshold.lt(FixidityLib.fixed1()), - "Electability threshold must be lower than 100%" - ); - emit ElectabilityThresholdSet(threshold); - return true; - } - - /** - * @notice Gets the election threshold. - * @return Threshold value as unwrapped fraction. - */ - function getElectabilityThreshold() external view returns (uint256) { - return electabilityThreshold.unwrap(); - } - - /** - * @notice Increments the number of total and pending votes for `group`. - * @param group The validator group to vote for. - * @param value The amount of gold to use to vote. - * @param lesser The group receiving fewer votes than `group`, or 0 if `group` has the - * fewest votes of any validator group. - * @param greater The group receiving more votes than `group`, or 0 if `group` has the - * most votes of any validator group. - * @return True upon success. - * @dev Fails if `group` is empty or not a validator group. - */ - function vote(address group, uint256 value, address lesser, address greater) - external - nonReentrant - returns (bool) - { - require(votes.total.eligible.contains(group), "Group not eligible"); - require(0 < value, "Vote value cannot be zero"); - require(canReceiveVotes(group, value), "Group cannot receive votes"); - address account = getAccounts().voteSignerToAccount(msg.sender); - - // Add group to the groups voted for by the account. - bool alreadyVotedForGroup = false; - address[] storage groups = votes.groupsVotedFor[account]; - for (uint256 i = 0; i < groups.length; i = i.add(1)) { - alreadyVotedForGroup = alreadyVotedForGroup || groups[i] == group; - } - if (!alreadyVotedForGroup) { - require( - allowedToVoteOverMaxNumberOfGroups[msg.sender] || groups.length < maxNumGroupsVotedFor, - "Voted for too many groups" - ); - groups.push(group); - } - - incrementPendingVotes(group, account, value); - incrementTotalVotes(account, group, value, lesser, greater); - getLockedGold().decrementNonvotingAccountBalance(account, value); - emit ValidatorGroupVoteCast(account, group, value); - return true; - } - - /** - * @notice Converts `account`'s pending votes for `group` to active votes. - * @param group The validator group to vote for. - * @return True upon success. - * @dev Pending votes cannot be activated until an election has been held. - */ - function activate(address group) external nonReentrant returns (bool) { - address account = getAccounts().voteSignerToAccount(msg.sender); - return _activate(group, account); - } - - /** - * @notice Converts `account`'s pending votes for `group` to active votes. - * @param group The validator group to vote for. - * @param account The validateor group account's pending votes to active votes - * @return True upon success. - * @dev Pending votes cannot be activated until an election has been held. - */ - function activateForAccount(address group, address account) external nonReentrant returns (bool) { - return _activate(group, account); - } - - function _activate(address group, address account) internal returns (bool) { - PendingVote storage pendingVote = votes.pending.forGroup[group].byAccount[account]; - require(pendingVote.epoch < getEpochNumber(), "Pending vote epoch not passed"); - uint256 value = pendingVote.value; - require(value > 0, "Vote value cannot be zero"); - decrementPendingVotes(group, account, value); - uint256 units = incrementActiveVotes(group, account, value); - emit ValidatorGroupVoteActivated(account, group, value, units); - return true; - } - - /** - * @notice Returns whether or not an account's votes for the specified group can be activated. - * @param account The account with pending votes. - * @param group The validator group that `account` has pending votes for. - * @return Whether or not `account` has activatable votes for `group`. - * @dev Pending votes cannot be activated until an election has been held. - */ - function hasActivatablePendingVotes(address account, address group) external view returns (bool) { - PendingVote storage pendingVote = votes.pending.forGroup[group].byAccount[account]; - return pendingVote.epoch < getEpochNumber() && pendingVote.value > 0; - } - - /** - * @notice Revokes `value` pending votes for `group` - * @param group The validator group to revoke votes from. - * @param value The number of votes to revoke. - * @param lesser The group receiving fewer votes than the group for which the vote was revoked, - * or 0 if that group has the fewest votes of any validator group. - * @param greater The group receiving more votes than the group for which the vote was revoked, - * or 0 if that group has the most votes of any validator group. - * @param index The index of the group in the account's voting list. - * @return True upon success. - * @dev Fails if the account has not voted on a validator group. - */ - function revokePending( - address group, - uint256 value, - address lesser, - address greater, - uint256 index - ) external nonReentrant returns (bool) { - require(group != address(0), "Group address zero"); - address account = getAccounts().voteSignerToAccount(msg.sender); - require(0 < value, "Vote value cannot be zero"); - require( - value <= getPendingVotesForGroupByAccount(group, account), - "Vote value larger than pending votes" - ); - decrementPendingVotes(group, account, value); - decrementTotalVotes(account, group, value, lesser, greater); - getLockedGold().incrementNonvotingAccountBalance(account, value); - if (getTotalVotesForGroupByAccount(group, account) == 0) { - deleteElement(votes.groupsVotedFor[account], group, index); - } - emit ValidatorGroupPendingVoteRevoked(account, group, value); - return true; - } - - /** - * @notice Revokes all active votes for `group` - * @param group The validator group to revoke votes from. - * @param lesser The group receiving fewer votes than the group for which the vote was revoked, - * or 0 if that group has the fewest votes of any validator group. - * @param greater The group receiving more votes than the group for which the vote was revoked, - * or 0 if that group has the most votes of any validator group. - * @param index The index of the group in the account's voting list. - * @return True upon success. - * @dev Fails if the account has not voted on a validator group. - */ - function revokeAllActive(address group, address lesser, address greater, uint256 index) - external - nonReentrant - returns (bool) - { - address account = getAccounts().voteSignerToAccount(msg.sender); - uint256 value = getActiveVotesForGroupByAccount(group, account); - return _revokeActive(group, value, lesser, greater, index); - } - - /** - * @notice Revokes `value` active votes for `group` - * @param group The validator group to revoke votes from. - * @param value The number of votes to revoke. - * @param lesser The group receiving fewer votes than the group for which the vote was revoked, - * or 0 if that group has the fewest votes of any validator group. - * @param greater The group receiving more votes than the group for which the vote was revoked, - * or 0 if that group has the most votes of any validator group. - * @param index The index of the group in the account's voting list. - * @return True upon success. - * @dev Fails if the account has not voted on a validator group. - */ - function revokeActive( - address group, - uint256 value, - address lesser, - address greater, - uint256 index - ) external nonReentrant returns (bool) { - return _revokeActive(group, value, lesser, greater, index); - } - - function _revokeActive( - address group, - uint256 value, - address lesser, - address greater, - uint256 index - ) internal returns (bool) { - // TODO(asa): Dedup with revokePending. - require(group != address(0), "Group address zero"); - address account = getAccounts().voteSignerToAccount(msg.sender); - require(0 < value, "Vote value cannot be zero"); - require( - value <= getActiveVotesForGroupByAccount(group, account), - "Vote value larger than active votes" - ); - uint256 units = decrementActiveVotes(group, account, value); - decrementTotalVotes(account, group, value, lesser, greater); - getLockedGold().incrementNonvotingAccountBalance(account, value); - if (getTotalVotesForGroupByAccount(group, account) == 0) { - deleteElement(votes.groupsVotedFor[account], group, index); - } - emit ValidatorGroupActiveVoteRevoked(account, group, value, units); - return true; - } - - /** - * @notice Decrements `value` pending or active votes for `group` from `account`. - * First revokes all pending votes and then, if `value` votes haven't - * been revoked yet, revokes additional active votes. - * Fundamentally calls `revokePending` and `revokeActive` but only resorts groups once. - * @param account The account whose votes to `group` should be decremented. - * @param group The validator group to decrement votes from. - * @param maxValue The maxinum number of votes to decrement and revoke. - * @param lesser The group receiving fewer votes than the group for which the vote was revoked, - * or 0 if that group has the fewest votes of any validator group. - * @param greater The group receiving more votes than the group for which the vote was revoked, - * or 0 if that group has the most votes of any validator group. - * @param index The index of the group in the account's voting list. - * @return uint256 Number of votes successfully decremented and revoked, with a max of `value`. - */ - function _decrementVotes( - address account, - address group, - uint256 maxValue, - address lesser, - address greater, - uint256 index - ) internal returns (uint256) { - uint256 remainingValue = maxValue; - uint256 pendingVotes = getPendingVotesForGroupByAccount(group, account); - if (pendingVotes > 0) { - uint256 decrementValue = Math.min(remainingValue, pendingVotes); - decrementPendingVotes(group, account, decrementValue); - emit ValidatorGroupPendingVoteRevoked(account, group, decrementValue); - remainingValue = remainingValue.sub(decrementValue); - } - uint256 activeVotes = getActiveVotesForGroupByAccount(group, account); - if (activeVotes > 0 && remainingValue > 0) { - uint256 decrementValue = Math.min(remainingValue, activeVotes); - uint256 units = decrementActiveVotes(group, account, decrementValue); - emit ValidatorGroupActiveVoteRevoked(account, group, decrementValue, units); - remainingValue = remainingValue.sub(decrementValue); - } - uint256 decrementedValue = maxValue.sub(remainingValue); - if (decrementedValue > 0) { - decrementTotalVotes(account, group, decrementedValue, lesser, greater); - if (getTotalVotesForGroupByAccount(group, account) == 0) { - deleteElement(votes.groupsVotedFor[account], group, index); - } - } - return decrementedValue; - } - - /** - * @notice Returns the total number of votes cast by an account. - * @param account The address of the account. - * @return The total number of votes cast by an account. - */ - function getTotalVotesByAccount(address account) external view returns (uint256) { - address[] memory groups = votes.groupsVotedFor[account]; - - if (groups.length > maxNumGroupsVotedFor) { - return cachedVotesByAccount[account].totalVotes; - } - - uint256 total = 0; - for (uint256 i = 0; i < groups.length; i = i.add(1)) { - total = total.add(getTotalVotesForGroupByAccount(groups[i], account)); - } - return total; - } - - /** - * @notice Counts and caches account's votes for group. - * @param account The address of the voting account. - * @param group The address of the validator group. - */ - function updateTotalVotesByAccountForGroup(address account, address group) public { - cachedVotesByAccount[account].totalVotes -= cachedVotesByAccount[account] - .cachedVotesPerGroup[group]; - uint256 newTotalVotesForGroupByAccount = getTotalVotesForGroupByAccount(group, account); - cachedVotesByAccount[account].cachedVotesPerGroup[group] = newTotalVotesForGroupByAccount; - cachedVotesByAccount[account].totalVotes += newTotalVotesForGroupByAccount; - } - - /** - * @notice Returns the pending votes for `group` made by `account`. - * @param group The address of the validator group. - * @param account The address of the voting account. - * @return The pending votes for `group` made by `account`. - */ - function getPendingVotesForGroupByAccount(address group, address account) - public - view - returns (uint256) - { - return votes.pending.forGroup[group].byAccount[account].value; - } - - /** - * @notice Returns the active votes for `group` made by `account`. - * @param group The address of the validator group. - * @param account The address of the voting account. - * @return The active votes for `group` made by `account`. - */ - function getActiveVotesForGroupByAccount(address group, address account) - public - view - returns (uint256) - { - return unitsToVotes(group, votes.active.forGroup[group].unitsByAccount[account]); - } - - /** - * @notice Returns the total votes for `group` made by `account`. - * @param group The address of the validator group. - * @param account The address of the voting account. - * @return The total votes for `group` made by `account`. - */ - function getTotalVotesForGroupByAccount(address group, address account) - public - view - returns (uint256) - { - uint256 pending = getPendingVotesForGroupByAccount(group, account); - uint256 active = getActiveVotesForGroupByAccount(group, account); - return pending.add(active); - } - - /** - * @notice Returns the active vote units for `group` made by `account`. - * @param group The address of the validator group. - * @param account The address of the voting account. - * @return The active vote units for `group` made by `account`. - */ - function getActiveVoteUnitsForGroupByAccount(address group, address account) - external - view - returns (uint256) - { - return votes.active.forGroup[group].unitsByAccount[account]; - } - - /** - * @notice Returns the total active vote units made for `group`. - * @param group The address of the validator group. - * @return The total active vote units made for `group`. - */ - function getActiveVoteUnitsForGroup(address group) external view returns (uint256) { - return votes.active.forGroup[group].totalUnits; - } - - /** - * @notice Returns the total votes made for `group`. - * @param group The address of the validator group. - * @return The total votes made for `group`. - */ - function getTotalVotesForGroup(address group) public view returns (uint256) { - return votes.pending.forGroup[group].total.add(votes.active.forGroup[group].total); - } - - /** - * @notice Returns the active votes made for `group`. - * @param group The address of the validator group. - * @return The active votes made for `group`. - */ - function getActiveVotesForGroup(address group) public view returns (uint256) { - return votes.active.forGroup[group].total; - } - - /** - * @notice Returns the pending votes made for `group`. - * @param group The address of the validator group. - * @return The pending votes made for `group`. - */ - function getPendingVotesForGroup(address group) public view returns (uint256) { - return votes.pending.forGroup[group].total; - } - - /** - * @notice Returns whether or not a group is eligible to receive votes. - * @return Whether or not a group is eligible to receive votes. - * @dev Eligible groups that have received their maximum number of votes cannot receive more. - */ - function getGroupEligibility(address group) external view returns (bool) { - return votes.total.eligible.contains(group); - } - - /** - * @notice Returns the amount of rewards that voters for `group` are due at the end of an epoch. - * @param group The group to calculate epoch rewards for. - * @param totalEpochRewards The total amount of rewards going to all voters. - * @param uptimes Array of Fixidity representations of the validators' uptimes, between 0 and 1. - * @return The amount of rewards that voters for `group` are due at the end of an epoch. - * @dev Eligible groups that have received their maximum number of votes cannot receive more. - */ - function getGroupEpochRewards( - address group, - uint256 totalEpochRewards, - uint256[] calldata uptimes - ) external view returns (uint256) { - IValidators validators = getValidators(); - // The group must meet the balance requirements for their voters to receive epoch rewards. - if (!validators.meetsAccountLockedGoldRequirements(group) || votes.active.total <= 0) { - return 0; - } - - FixidityLib.Fraction memory votePortion = FixidityLib.newFixedFraction( - votes.active.forGroup[group].total, - votes.active.total - ); - FixidityLib.Fraction memory score = FixidityLib.wrap( - validators.calculateGroupEpochScore(uptimes) - ); - FixidityLib.Fraction memory slashingMultiplier = FixidityLib.wrap( - validators.getValidatorGroupSlashingMultiplier(group) - ); - return - FixidityLib - .newFixed(totalEpochRewards) - .multiply(votePortion) - .multiply(score) - .multiply(slashingMultiplier) - .fromFixed(); - } - - /** - * @notice Distributes epoch rewards to voters for `group` in the form of active votes. - * @param group The group whose voters will receive rewards. - * @param value The amount of rewards to distribute to voters for the group. - * @param lesser The group receiving fewer votes than `group` after the rewards are added. - * @param greater The group receiving more votes than `group` after the rewards are added. - * @dev Can only be called directly by the protocol. - */ - function distributeEpochRewards(address group, uint256 value, address lesser, address greater) - external - onlyVm - { - _distributeEpochRewards(group, value, lesser, greater); - } - - /** - * @notice Distributes epoch rewards to voters for `group` in the form of active votes. - * @param group The group whose voters will receive rewards. - * @param value The amount of rewards to distribute to voters for the group. - * @param lesser The group receiving fewer votes than `group` after the rewards are added. - * @param greater The group receiving more votes than `group` after the rewards are added. - */ - function _distributeEpochRewards(address group, uint256 value, address lesser, address greater) - internal - { - if (votes.total.eligible.contains(group)) { - uint256 newVoteTotal = votes.total.eligible.getValue(group).add(value); - votes.total.eligible.update(group, newVoteTotal, lesser, greater); - } - - votes.active.forGroup[group].total = votes.active.forGroup[group].total.add(value); - votes.active.total = votes.active.total.add(value); - emit EpochRewardsDistributedToVoters(group, value); - } - - /** - * @notice Increments the number of total votes for `group` by `value`. - * @param group The validator group whose vote total should be incremented. - * @param value The number of votes to increment. - * @param lesser The group receiving fewer votes than the group for which the vote was cast, - * or 0 if that group has the fewest votes of any validator group. - * @param greater The group receiving more votes than the group for which the vote was cast, - * or 0 if that group has the most votes of any validator group. - */ - function incrementTotalVotes( - address account, - address group, - uint256 value, - address lesser, - address greater - ) private { - uint256 newVoteTotal = votes.total.eligible.getValue(group).add(value); - votes.total.eligible.update(group, newVoteTotal, lesser, greater); - - if (allowedToVoteOverMaxNumberOfGroups[account]) { - updateTotalVotesByAccountForGroup(account, group); - } - } - - /** - * @notice Decrements the number of total votes for `group` by `value`. - * @param account The address of the voting account. - * @param group The validator group whose vote total should be decremented. - * @param value The number of votes to decrement. - * @param lesser The group receiving fewer votes than the group for which the vote was revoked, - * or 0 if that group has the fewest votes of any validator group. - * @param greater The group receiving more votes than the group for which the vote was revoked, - * or 0 if that group has the most votes of any validator group. - */ - function decrementTotalVotes( - address account, - address group, - uint256 value, - address lesser, - address greater - ) private { - if (votes.total.eligible.contains(group)) { - uint256 newVoteTotal = votes.total.eligible.getValue(group).sub(value); - votes.total.eligible.update(group, newVoteTotal, lesser, greater); - } - - if (allowedToVoteOverMaxNumberOfGroups[account]) { - updateTotalVotesByAccountForGroup(account, group); - } - } - - /** - * @notice Marks a group ineligible for electing validators. - * @param group The address of the validator group. - * @dev Can only be called by the registered "Validators" contract. - */ - function markGroupIneligible(address group) - external - onlyRegisteredContract(VALIDATORS_REGISTRY_ID) - { - votes.total.eligible.remove(group); - emit ValidatorGroupMarkedIneligible(group); - } - - /** - * @notice Marks a group eligible for electing validators. - * @param group The address of the validator group. - * @param lesser The address of the group that has received fewer votes than this group. - * @param greater The address of the group that has received more votes than this group. - */ - function markGroupEligible(address group, address lesser, address greater) - external - onlyRegisteredContract(VALIDATORS_REGISTRY_ID) - { - uint256 value = getTotalVotesForGroup(group); - votes.total.eligible.insert(group, value, lesser, greater); - emit ValidatorGroupMarkedEligible(group); - } - - /** - * @notice Increments the number of pending votes for `group` made by `account`. - * @param group The address of the validator group. - * @param account The address of the voting account. - * @param value The number of votes. - */ - function incrementPendingVotes(address group, address account, uint256 value) private { - PendingVotes storage pending = votes.pending; - pending.total = pending.total.add(value); - - GroupPendingVotes storage groupPending = pending.forGroup[group]; - groupPending.total = groupPending.total.add(value); - - PendingVote storage pendingVote = groupPending.byAccount[account]; - pendingVote.value = pendingVote.value.add(value); - pendingVote.epoch = getEpochNumber(); - } - - /** - * @notice Decrements the number of pending votes for `group` made by `account`. - * @param group The address of the validator group. - * @param account The address of the voting account. - * @param value The number of votes. - */ - function decrementPendingVotes(address group, address account, uint256 value) private { - PendingVotes storage pending = votes.pending; - pending.total = pending.total.sub(value); - - GroupPendingVotes storage groupPending = pending.forGroup[group]; - groupPending.total = groupPending.total.sub(value); - - PendingVote storage pendingVote = groupPending.byAccount[account]; - pendingVote.value = pendingVote.value.sub(value); - if (pendingVote.value == 0) { - pendingVote.epoch = 0; - } - } - - /** - * @notice Increments the number of active votes for `group` made by `account`. - * @param group The address of the validator group. - * @param account The address of the voting account. - * @param value The number of votes. - */ - function incrementActiveVotes(address group, address account, uint256 value) - private - returns (uint256) - { - ActiveVotes storage active = votes.active; - active.total = active.total.add(value); - - uint256 units = votesToUnits(group, value); - - GroupActiveVotes storage groupActive = active.forGroup[group]; - groupActive.total = groupActive.total.add(value); - - groupActive.totalUnits = groupActive.totalUnits.add(units); - groupActive.unitsByAccount[account] = groupActive.unitsByAccount[account].add(units); - return units; - } - - /** - * @notice Decrements the number of active votes for `group` made by `account`. - * @param group The address of the validator group. - * @param account The address of the voting account. - * @param value The number of votes. - */ - function decrementActiveVotes(address group, address account, uint256 value) - private - returns (uint256) - { - ActiveVotes storage active = votes.active; - active.total = active.total.sub(value); - - // Rounding may cause votesToUnits to return 0 for value != 0, preventing users - // from revoking the last of their votes. The case where value == votes is special cased - // to prevent this. - uint256 units = 0; - uint256 activeVotes = getActiveVotesForGroupByAccount(group, account); - GroupActiveVotes storage groupActive = active.forGroup[group]; - if (activeVotes == value) { - units = groupActive.unitsByAccount[account]; - } else { - units = votesToUnits(group, value); - } - - groupActive.total = groupActive.total.sub(value); - groupActive.totalUnits = groupActive.totalUnits.sub(units); - groupActive.unitsByAccount[account] = groupActive.unitsByAccount[account].sub(units); - return units; - } - - /** - * @notice Returns the number of units corresponding to `value` active votes. - * @param group The address of the validator group. - * @param value The number of active votes. - * @return The corresponding number of units. - */ - function votesToUnits(address group, uint256 value) private view returns (uint256) { - if (votes.active.forGroup[group].totalUnits == 0) { - return value.mul(UNIT_PRECISION_FACTOR); - } else { - return - value.mul(votes.active.forGroup[group].totalUnits).div(votes.active.forGroup[group].total); - } - } - - /** - * @notice Returns the number of active votes corresponding to `value` units. - * @param group The address of the validator group. - * @param value The number of units. - * @return The corresponding number of active votes. - */ - function unitsToVotes(address group, uint256 value) private view returns (uint256) { - if (votes.active.forGroup[group].totalUnits == 0) { - return 0; - } else { - return - value.mul(votes.active.forGroup[group].total).div(votes.active.forGroup[group].totalUnits); - } - } - - /** - * @notice Returns the groups that `account` has voted for. - * @param account The address of the account casting votes. - * @return The groups that `account` has voted for. - */ - function getGroupsVotedForByAccount(address account) external view returns (address[] memory) { - return votes.groupsVotedFor[account]; - } - - /** - * @notice Deletes an element from a list of addresses. - * @param list The list of addresses. - * @param element The address to delete. - * @param index The index of `element` in the list. - */ - function deleteElement(address[] storage list, address element, uint256 index) private { - require(index < list.length && list[index] == element, "Bad index"); - uint256 lastIndex = list.length.sub(1); - list[index] = list[lastIndex]; - list.length = lastIndex; - } - - /** - * @notice Returns whether or not a group can receive the specified number of votes. - * @param group The address of the group. - * @param value The number of votes. - * @return Whether or not a group can receive the specified number of votes. - * @dev Votes are not allowed to be cast that would increase a group's proportion of locked gold - * voting for it to greater than - * (numGroupMembers + 1) / min(maxElectableValidators, numRegisteredValidators) - * @dev Note that groups may still receive additional votes via rewards even if this function - * returns false. - */ - function canReceiveVotes(address group, uint256 value) public view returns (bool) { - uint256 totalVotesForGroup = getTotalVotesForGroup(group).add(value); - uint256 left = totalVotesForGroup.mul( - Math.min(electableValidators.max, getValidators().getNumRegisteredValidators()) - ); - uint256 right = getValidators().getGroupNumMembers(group).add(1).mul( - getLockedGold().getTotalLockedGold() - ); - return left <= right; - } - - /** - * @notice Returns the number of votes that a group can receive. - * @param group The address of the group. - * @return The number of votes that a group can receive. - * @dev Votes are not allowed to be cast that would increase a group's proportion of locked gold - * voting for it to greater than - * (numGroupMembers + 1) / min(maxElectableValidators, numRegisteredValidators) - * @dev Note that a group's vote total may exceed this number through rewards or config changes. - */ - function getNumVotesReceivable(address group) external view returns (uint256) { - uint256 numerator = getValidators().getGroupNumMembers(group).add(1).mul( - getLockedGold().getTotalLockedGold() - ); - uint256 denominator = Math.min( - electableValidators.max, - getValidators().getNumRegisteredValidators() - ); - return numerator.div(denominator); - } - - /** - * @notice Returns the total votes received across all groups. - * @return The total votes received across all groups. - */ - function getTotalVotes() public view returns (uint256) { - return votes.active.total.add(votes.pending.total); - } - - /** - * @notice Returns the active votes received across all groups. - * @return The active votes received across all groups. - */ - function getActiveVotes() public view returns (uint256) { - return votes.active.total; - } - - /** - * @notice Returns the list of validator groups eligible to elect validators. - * @return The list of validator groups eligible to elect validators. - */ - function getEligibleValidatorGroups() external view returns (address[] memory) { - return votes.total.eligible.getKeys(); - } - - /** - * @notice Returns list of all validator groups and the number of votes they've received. - * @return List of all validator groups - * @return Number of votes each validator group received. - */ - function getTotalVotesForEligibleValidatorGroups() - external - view - returns (address[] memory groups, uint256[] memory values) - { - return votes.total.eligible.getElements(); - } - - /** - * @notice Returns a list of elected validators with seats allocated to groups via the D'Hondt - * method. - * @return The list of elected validators. - */ - function electValidatorSigners() external view returns (address[] memory) { - return electNValidatorSigners(electableValidators.min, electableValidators.max); - } - - /** - * @notice Returns a list of elected validators with seats allocated to groups via the D'Hondt - * method. - * @return The list of elected validators. - * @dev See https://en.wikipedia.org/wiki/D%27Hondt_method#Allocation for more information. - */ - function electNValidatorSigners(uint256 minElectableValidators, uint256 maxElectableValidators) - public - view - returns (address[] memory) - { - // Groups must have at least `electabilityThreshold` proportion of the total votes to be - // considered for the election. - uint256 requiredVotes = electabilityThreshold - .multiply(FixidityLib.newFixed(getTotalVotes())) - .fromFixed(); - // Only consider groups with at least `requiredVotes` but do not consider more groups than the - // max number of electable validators. - uint256 numElectionGroups = votes.total.eligible.numElementsGreaterThan( - requiredVotes, - maxElectableValidators - ); - address[] memory electionGroups = votes.total.eligible.headN(numElectionGroups); - uint256[] memory numMembers = getValidators().getGroupsNumMembers(electionGroups); - // Holds the number of members elected for each of the eligible validator groups. - uint256[] memory numMembersElected = new uint256[](electionGroups.length); - uint256 totalNumMembersElected = 0; - - uint256[] memory keys = new uint256[](electionGroups.length); - FixidityLib.Fraction[] memory votesForNextMember = new FixidityLib.Fraction[]( - electionGroups.length - ); - for (uint256 i = 0; i < electionGroups.length; i = i.add(1)) { - keys[i] = i; - votesForNextMember[i] = FixidityLib.newFixed( - votes.total.eligible.getValue(electionGroups[i]) - ); - } - - // Assign a number of seats to each validator group. - while (totalNumMembersElected < maxElectableValidators && electionGroups.length > 0) { - uint256 groupIndex = keys[0]; - // All electable validators have been elected. - if (votesForNextMember[groupIndex].unwrap() == 0) break; - // All members of the group have been elected - if (numMembers[groupIndex] <= numMembersElected[groupIndex]) { - votesForNextMember[groupIndex] = FixidityLib.wrap(0); - } else { - // Elect the next member from the validator group - numMembersElected[groupIndex] = numMembersElected[groupIndex].add(1); - totalNumMembersElected = totalNumMembersElected.add(1); - // If there are already n elected members in a group, the votes for the next member - // are total votes of group divided by n+1 - votesForNextMember[groupIndex] = FixidityLib - .newFixed(votes.total.eligible.getValue(electionGroups[groupIndex])) - .divide(FixidityLib.newFixed(numMembersElected[groupIndex].add(1))); - } - Heap.heapifyDown(keys, votesForNextMember); - } - require(totalNumMembersElected >= minElectableValidators, "Not enough elected validators"); - // Grab the top validators from each group that won seats. - address[] memory electedValidators = new address[](totalNumMembersElected); - totalNumMembersElected = 0; - for (uint256 i = 0; i < electionGroups.length; i = i.add(1)) { - // We use the validating delegate if one is set. - address[] memory electedGroupValidators = getValidators().getTopGroupValidators( - electionGroups[i], - numMembersElected[i] - ); - for (uint256 j = 0; j < electedGroupValidators.length; j = j.add(1)) { - electedValidators[totalNumMembersElected] = electedGroupValidators[j]; - totalNumMembersElected = totalNumMembersElected.add(1); - } - } - return electedValidators; - } - - /** - * @notice Returns get current validator signers using the precompiles. - * @return List of current validator signers. - */ - function getCurrentValidatorSigners() public view returns (address[] memory) { - uint256 n = numberValidatorsInCurrentSet(); - address[] memory res = new address[](n); - for (uint256 i = 0; i < n; i = i.add(1)) { - res[i] = validatorSignerAddressFromCurrentSet(i); - } - return res; - } - - /** - * @notice Allows to turn on/off voting over maxNumGroupsVotedFor. - * Once this is turned on and account voted for more than maxNumGroupsVotedFor, - * it is account's obligation to run updateTotalVotesByAccountForGroup once a day. - * If not run, voting power of account will not reflect rewards awarded. - * @param flag The on/off flag. - */ - function setAllowedToVoteOverMaxNumberOfGroups(bool flag) public { - address account = getAccounts().voteSignerToAccount(msg.sender); - IValidators validators = getValidators(); - require( - !validators.isValidator(account), - "Validators cannot vote for more than max number of groups" - ); - require( - !validators.isValidatorGroup(account), - "Validator groups cannot vote for more than max number of groups" - ); - - if (!flag) { - require( - votes.groupsVotedFor[account].length <= maxNumGroupsVotedFor, - "Too many groups voted for!" - ); - } - - allowedToVoteOverMaxNumberOfGroups[account] = flag; - emit AllowedToVoteOverMaxNumberOfGroups(account, flag); - } - - // Struct to hold local variables for `forceDecrementVotes`. - // Needed to prevent solc error of "stack too deep" from too many local vars. - struct DecrementVotesInfo { - address[] groups; - uint256 remainingValue; - } - - /** - * @notice Reduces the total amount of `account`'s voting gold by `value` by - * iterating over all groups voted for by account. - * @param account Address to revoke votes from. - * @param value Maximum amount of votes to revoke. - * @param lessers The groups receiving fewer votes than the i'th `group`, or 0 if - * the i'th `group` has the fewest votes of any validator group. - * @param greaters The groups receivier more votes than the i'th `group`, or 0 if - * the i'th `group` has the most votes of any validator group. - * @param indices The indices of the i'th group in the account's voting list. - * @return Number of votes successfully decremented. - */ - function forceDecrementVotes( - address account, - uint256 value, - address[] calldata lessers, - address[] calldata greaters, - uint256[] calldata indices - ) external nonReentrant onlyRegisteredContract(LOCKED_GOLD_REGISTRY_ID) returns (uint256) { - require(value > 0, "Decrement value must be greater than 0."); - DecrementVotesInfo memory info = DecrementVotesInfo(votes.groupsVotedFor[account], value); - require( - lessers.length <= info.groups.length && - lessers.length == greaters.length && - greaters.length == indices.length, - "Input lengths must be correspond." - ); - // Iterate in reverse order to hopefully optimize removing pending votes before active votes - // And to attempt to preserve `account`'s earliest votes (assuming earliest = prefered) - for (uint256 i = info.groups.length; i > 0; i = i.sub(1)) { - info.remainingValue = info.remainingValue.sub( - _decrementVotes( - account, - info.groups[i.sub(1)], - info.remainingValue, - lessers[i.sub(1)], - greaters[i.sub(1)], - indices[i.sub(1)] - ) - ); - if (info.remainingValue == 0) { - break; - } - } - require(info.remainingValue == 0, "Failure to decrement all votes."); - return value; - } -} diff --git a/packages/protocol/contracts/governance/EpochRewards.sol b/packages/protocol/contracts/governance/EpochRewards.sol deleted file mode 100644 index 0c329e3e6..000000000 --- a/packages/protocol/contracts/governance/EpochRewards.sol +++ /dev/null @@ -1,552 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "../common/CalledByVm.sol"; -import "../common/FixidityLib.sol"; -import "../common/Freezable.sol"; -import "../common/Initializable.sol"; -import "../common/UsingRegistry.sol"; -import "../common/UsingPrecompiles.sol"; -import "../common/interfaces/ICeloVersionedContract.sol"; - -/** - * @title Contract for calculating epoch rewards. - */ -contract EpochRewards is - ICeloVersionedContract, - Ownable, - Initializable, - UsingPrecompiles, - UsingRegistry, - Freezable, - CalledByVm -{ - using FixidityLib for FixidityLib.Fraction; - using SafeMath for uint256; - - uint256 constant GENESIS_GOLD_SUPPLY = 600000000 ether; // 600 million Gold - uint256 constant GOLD_SUPPLY_CAP = 1000000000 ether; // 1 billion Gold - uint256 constant YEARS_LINEAR = 15; - uint256 constant SECONDS_LINEAR = YEARS_LINEAR * 365 * 1 days; - - // This struct governs how the rewards multiplier should deviate from 1.0 based on the ratio of - // supply remaining to target supply remaining. - struct RewardsMultiplierAdjustmentFactors { - FixidityLib.Fraction underspend; - FixidityLib.Fraction overspend; - } - - // This struct governs the multiplier on the target rewards to give out in a given epoch due to - // potential deviations in the actual Gold total supply from the target total supply. - // In the case where the actual exceeds the target (i.e. the protocol has "overspent" with - // respect to epoch rewards and payments) the rewards multiplier will be less than one. - // In the case where the actual is less than the target (i.e. the protocol has "underspent" with - // respect to epoch rewards and payments) the rewards multiplier will be greater than one. - struct RewardsMultiplierParameters { - RewardsMultiplierAdjustmentFactors adjustmentFactors; - // The maximum rewards multiplier. - FixidityLib.Fraction max; - } - - // This struct governs the target yield awarded to voters in validator elections. - struct TargetVotingYieldParameters { - // The target yield awarded to users voting in validator elections. - FixidityLib.Fraction target; - // Governs the adjustment of the target yield based on the deviation of the percentage of - // Gold voting in validator elections from the `targetVotingGoldFraction`. - FixidityLib.Fraction adjustmentFactor; - // The maximum target yield awarded to users voting in validator elections. - FixidityLib.Fraction max; - } - - uint256 public startTime = 0; - RewardsMultiplierParameters private rewardsMultiplierParams; - TargetVotingYieldParameters private targetVotingYieldParams; - FixidityLib.Fraction private targetVotingGoldFraction; - FixidityLib.Fraction private communityRewardFraction; - FixidityLib.Fraction private carbonOffsettingFraction; - address public carbonOffsettingPartner; - uint256 public targetValidatorEpochPayment; - - event TargetVotingGoldFractionSet(uint256 fraction); - event CommunityRewardFractionSet(uint256 fraction); - event CarbonOffsettingFundSet(address indexed partner, uint256 fraction); - event TargetValidatorEpochPaymentSet(uint256 payment); - event TargetVotingYieldParametersSet(uint256 max, uint256 adjustmentFactor); - event TargetVotingYieldSet(uint256 target); - event RewardsMultiplierParametersSet( - uint256 max, - uint256 underspendAdjustmentFactor, - uint256 overspendAdjustmentFactor - ); - - event TargetVotingYieldUpdated(uint256 fraction); - - /** - * @notice Returns the storage, major, minor, and patch version of the contract. - * @return Storage version of the contract. - * @return Major version of the contract. - * @return Minor version of the contract. - * @return Patch version of the contract. - */ - function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { - return (1, 1, 1, 0); - } - - /** - * @notice Sets initialized == true on implementation contracts - * @param test Set to true to skip implementation initialization - */ - constructor(bool test) public Initializable(test) {} - - /** - * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. - * @param registryAddress The address of the registry contract. - * @param targetVotingYieldInitial The initial relative target block reward for voters. - * @param targetVotingYieldMax The max relative target block reward for voters. - * @param targetVotingYieldAdjustmentFactor The target block reward adjustment factor for voters. - * @param rewardsMultiplierMax The max multiplier on target epoch rewards. - * @param rewardsMultiplierUnderspendAdjustmentFactor Adjusts the multiplier on target epoch - * rewards when the protocol is running behind the target Gold supply. - * @param rewardsMultiplierOverspendAdjustmentFactor Adjusts the multiplier on target epoch - * rewards when the protocol is running ahead of the target Gold supply. - * @param _targetVotingGoldFraction The percentage of floating Gold voting to target. - * @param _targetValidatorEpochPayment The target validator epoch payment. - * @param _communityRewardFraction The percentage of rewards that go the community funds. - * @param _carbonOffsettingPartner The address of the carbon offsetting partner. - * @param _carbonOffsettingFraction The percentage of rewards going to carbon offsetting partner. - * @dev Should be called only once. - */ - function initialize( - address registryAddress, - uint256 targetVotingYieldInitial, - uint256 targetVotingYieldMax, - uint256 targetVotingYieldAdjustmentFactor, - uint256 rewardsMultiplierMax, - uint256 rewardsMultiplierUnderspendAdjustmentFactor, - uint256 rewardsMultiplierOverspendAdjustmentFactor, - uint256 _targetVotingGoldFraction, - uint256 _targetValidatorEpochPayment, - uint256 _communityRewardFraction, - address _carbonOffsettingPartner, - uint256 _carbonOffsettingFraction - ) external initializer { - _transferOwnership(msg.sender); - setRegistry(registryAddress); - setTargetVotingYieldParameters(targetVotingYieldMax, targetVotingYieldAdjustmentFactor); - setRewardsMultiplierParameters( - rewardsMultiplierMax, - rewardsMultiplierUnderspendAdjustmentFactor, - rewardsMultiplierOverspendAdjustmentFactor - ); - setTargetVotingGoldFraction(_targetVotingGoldFraction); - setTargetValidatorEpochPayment(_targetValidatorEpochPayment); - setCommunityRewardFraction(_communityRewardFraction); - setCarbonOffsettingFund(_carbonOffsettingPartner, _carbonOffsettingFraction); - setTargetVotingYield(targetVotingYieldInitial); - startTime = now; - } - - /** - * @notice Returns the target voting yield parameters. - * @return The target factor for target voting yield. - * @return The max factor for target voting yield. - * @return The adjustment factor for target voting yield. - */ - function getTargetVotingYieldParameters() external view returns (uint256, uint256, uint256) { - TargetVotingYieldParameters storage params = targetVotingYieldParams; - return (params.target.unwrap(), params.max.unwrap(), params.adjustmentFactor.unwrap()); - } - - /** - * @notice Returns the rewards multiplier parameters. - * @return The max multiplier. - * @return The underspend adjustment factors. - * @return The overspend adjustment factors. - */ - function getRewardsMultiplierParameters() external view returns (uint256, uint256, uint256) { - RewardsMultiplierParameters storage params = rewardsMultiplierParams; - return ( - params.max.unwrap(), - params.adjustmentFactors.underspend.unwrap(), - params.adjustmentFactors.overspend.unwrap() - ); - } - - /** - * @notice Sets the community reward percentage - * @param value The percentage of the total reward to be sent to the community funds. - * @return True upon success. - */ - function setCommunityRewardFraction(uint256 value) public onlyOwner returns (bool) { - require( - value != communityRewardFraction.unwrap() && value < FixidityLib.fixed1().unwrap(), - "Value must be different from existing community reward fraction and less than 1" - ); - communityRewardFraction = FixidityLib.wrap(value); - emit CommunityRewardFractionSet(value); - return true; - } - - /** - * @notice Returns the community reward fraction. - * @return The percentage of total reward which goes to the community funds. - */ - function getCommunityRewardFraction() external view returns (uint256) { - return communityRewardFraction.unwrap(); - } - - /** - * @notice Sets the carbon offsetting fund. - * @param partner The address of the carbon offsetting partner. - * @param value The percentage of the total reward to be sent to the carbon offsetting partner. - * @return True upon success. - */ - function setCarbonOffsettingFund(address partner, uint256 value) public onlyOwner returns (bool) { - require( - partner != carbonOffsettingPartner || value != carbonOffsettingFraction.unwrap(), - "Partner and value must be different from existing carbon offsetting fund" - ); - require(value < FixidityLib.fixed1().unwrap(), "Value must be less than 1"); - carbonOffsettingPartner = partner; - carbonOffsettingFraction = FixidityLib.wrap(value); - emit CarbonOffsettingFundSet(partner, value); - return true; - } - - /** - * @notice Returns the carbon offsetting partner reward fraction. - * @return The percentage of total reward which goes to the carbon offsetting partner. - */ - function getCarbonOffsettingFraction() external view returns (uint256) { - return carbonOffsettingFraction.unwrap(); - } - - /** - * @notice Sets the target voting Gold fraction. - * @param value The percentage of floating Gold voting to target. - * @return True upon success. - */ - function setTargetVotingGoldFraction(uint256 value) public onlyOwner returns (bool) { - require(value != targetVotingGoldFraction.unwrap(), "Target voting gold fraction unchanged"); - require( - value < FixidityLib.fixed1().unwrap(), - "Target voting gold fraction cannot be larger than 1" - ); - targetVotingGoldFraction = FixidityLib.wrap(value); - emit TargetVotingGoldFractionSet(value); - return true; - } - - /** - * @notice Returns the target voting Gold fraction. - * @return The percentage of floating Gold voting to target. - */ - function getTargetVotingGoldFraction() external view returns (uint256) { - return targetVotingGoldFraction.unwrap(); - } - - /** - * @notice Sets the target per-epoch payment in Celo Dollars for validators. - * @param value The value in Celo Dollars. - * @return True upon success. - */ - function setTargetValidatorEpochPayment(uint256 value) public onlyOwner returns (bool) { - require(value != targetValidatorEpochPayment, "Target validator epoch payment unchanged"); - targetValidatorEpochPayment = value; - emit TargetValidatorEpochPaymentSet(value); - return true; - } - - /** - * @notice Sets the rewards multiplier parameters. - * @param max The max multiplier on target epoch rewards. - * @param underspendAdjustmentFactor Adjusts the multiplier on target epoch rewards when the - * protocol is running behind the target Gold supply. - * @param overspendAdjustmentFactor Adjusts the multiplier on target epoch rewards when the - * protocol is running ahead of the target Gold supply. - * @return True upon success. - */ - function setRewardsMultiplierParameters( - uint256 max, - uint256 underspendAdjustmentFactor, - uint256 overspendAdjustmentFactor - ) public onlyOwner returns (bool) { - require( - max != rewardsMultiplierParams.max.unwrap() || - overspendAdjustmentFactor != rewardsMultiplierParams.adjustmentFactors.overspend.unwrap() || - underspendAdjustmentFactor != rewardsMultiplierParams.adjustmentFactors.underspend.unwrap(), - "Bad rewards multiplier parameters" - ); - rewardsMultiplierParams = RewardsMultiplierParameters( - RewardsMultiplierAdjustmentFactors( - FixidityLib.wrap(underspendAdjustmentFactor), - FixidityLib.wrap(overspendAdjustmentFactor) - ), - FixidityLib.wrap(max) - ); - emit RewardsMultiplierParametersSet(max, underspendAdjustmentFactor, overspendAdjustmentFactor); - return true; - } - - /** - * @notice Sets the target voting yield parameters. - * @param max The max relative target block reward for voters. - * @param adjustmentFactor The target block reward adjustment factor for voters. - * @return True upon success. - */ - function setTargetVotingYieldParameters(uint256 max, uint256 adjustmentFactor) - public - onlyOwner - returns (bool) - { - require( - max != targetVotingYieldParams.max.unwrap() || - adjustmentFactor != targetVotingYieldParams.adjustmentFactor.unwrap(), - "Bad target voting yield parameters" - ); - targetVotingYieldParams.max = FixidityLib.wrap(max); - targetVotingYieldParams.adjustmentFactor = FixidityLib.wrap(adjustmentFactor); - require( - targetVotingYieldParams.max.lt(FixidityLib.fixed1()), - "Max target voting yield must be lower than 100%" - ); - emit TargetVotingYieldParametersSet(max, adjustmentFactor); - return true; - } - - /** - * @notice Sets the target voting yield. Uses fixed point arithmetic - * for protection against overflow. - * @param targetVotingYield The relative target block reward for voters. - * @return True upon success. - */ - function setTargetVotingYield(uint256 targetVotingYield) public onlyOwner returns (bool) { - FixidityLib.Fraction memory target = FixidityLib.wrap(targetVotingYield); - require( - target.lte(targetVotingYieldParams.max), - "Target voting yield must be less than or equal to max" - ); - targetVotingYieldParams.target = target; - emit TargetVotingYieldSet(targetVotingYield); - return true; - } - - /** - * @notice Returns the target Gold supply according to the epoch rewards target schedule. - * @return The target Gold supply according to the epoch rewards target schedule. - */ - function getTargetGoldTotalSupply() public view returns (uint256) { - uint256 timeSinceInitialization = now.sub(startTime); - if (timeSinceInitialization < SECONDS_LINEAR) { - // Pay out half of all block rewards linearly. - uint256 linearRewards = GOLD_SUPPLY_CAP.sub(GENESIS_GOLD_SUPPLY).div(2); - uint256 targetRewards = linearRewards.mul(timeSinceInitialization).div(SECONDS_LINEAR); - return targetRewards.add(GENESIS_GOLD_SUPPLY); - } else { - require(false, "Block reward calculation for years 15-30 unimplemented"); - return 0; - } - } - - /** - * @notice Returns the rewards multiplier based on the current and target Gold supplies. - * @param targetGoldSupplyIncrease The target increase in current Gold supply. - * @return The rewards multiplier based on the current and target Gold supplies. - */ - function _getRewardsMultiplier(uint256 targetGoldSupplyIncrease) - internal - view - returns (FixidityLib.Fraction memory) - { - uint256 targetSupply = getTargetGoldTotalSupply(); - uint256 totalSupply = getGoldToken().totalSupply(); - uint256 remainingSupply = GOLD_SUPPLY_CAP.sub(totalSupply.add(targetGoldSupplyIncrease)); - uint256 targetRemainingSupply = GOLD_SUPPLY_CAP.sub(targetSupply); - FixidityLib.Fraction memory remainingToTargetRatio = FixidityLib - .newFixed(remainingSupply) - .divide(FixidityLib.newFixed(targetRemainingSupply)); - if (remainingToTargetRatio.gt(FixidityLib.fixed1())) { - FixidityLib.Fraction memory delta = remainingToTargetRatio - .subtract(FixidityLib.fixed1()) - .multiply(rewardsMultiplierParams.adjustmentFactors.underspend); - FixidityLib.Fraction memory multiplier = FixidityLib.fixed1().add(delta); - if (multiplier.lt(rewardsMultiplierParams.max)) { - return multiplier; - } else { - return rewardsMultiplierParams.max; - } - } else if (remainingToTargetRatio.lt(FixidityLib.fixed1())) { - FixidityLib.Fraction memory delta = FixidityLib - .fixed1() - .subtract(remainingToTargetRatio) - .multiply(rewardsMultiplierParams.adjustmentFactors.overspend); - if (delta.lt(FixidityLib.fixed1())) { - return FixidityLib.fixed1().subtract(delta); - } else { - return FixidityLib.wrap(0); - } - } else { - return FixidityLib.fixed1(); - } - } - - /** - * @notice Returns the total target epoch rewards for voters. - * @return the total target epoch rewards for voters. - */ - function getTargetVoterRewards() public view returns (uint256) { - return - FixidityLib - .newFixed(getElection().getActiveVotes()) - .multiply(targetVotingYieldParams.target) - .fromFixed(); - } - - /** - * @notice Returns the total target epoch payments to validators, converted to Gold. - * @return The total target epoch payments to validators, converted to Gold. - */ - function getTargetTotalEpochPaymentsInGold() public view returns (uint256) { - address stableTokenAddress = registry.getAddressForOrDie(STABLE_TOKEN_REGISTRY_ID); - (uint256 numerator, uint256 denominator) = getSortedOracles().medianRate(stableTokenAddress); - return - numberValidatorsInCurrentSet().mul(targetValidatorEpochPayment).mul(denominator).div( - numerator - ); - } - - /** - * @notice Returns the target gold supply increase used in calculating the rewards multiplier. - * @return The target increase in gold w/out the rewards multiplier. - */ - function _getTargetGoldSupplyIncrease() internal view returns (uint256) { - uint256 targetEpochRewards = getTargetVoterRewards(); - uint256 targetTotalEpochPaymentsInGold = getTargetTotalEpochPaymentsInGold(); - uint256 targetGoldSupplyIncrease = targetEpochRewards.add(targetTotalEpochPaymentsInGold); - // increase /= (1 - fraction) st the final community reward is fraction * increase - targetGoldSupplyIncrease = FixidityLib - .newFixed(targetGoldSupplyIncrease) - .divide( - FixidityLib.newFixed(1).subtract(communityRewardFraction).subtract(carbonOffsettingFraction) - ) - .fromFixed(); - return targetGoldSupplyIncrease; - } - - /** - * @notice Returns the rewards multiplier based on the current and target Gold supplies. - * @return The rewards multiplier based on the current and target Gold supplies. - */ - function getRewardsMultiplier() external view returns (uint256) { - return _getRewardsMultiplier(_getTargetGoldSupplyIncrease()).unwrap(); - } - - /** - * @notice Returns the fraction of floating Gold being used for voting in validator elections. - * @return The fraction of floating Gold being used for voting in validator elections. - */ - function getVotingGoldFraction() public view returns (uint256) { - uint256 liquidGold = getGoldToken().totalSupply().sub(getReserve().getReserveGoldBalance()); - uint256 votingGold = getElection().getTotalVotes(); - return FixidityLib.newFixed(votingGold).divide(FixidityLib.newFixed(liquidGold)).unwrap(); - } - - /** - * @notice Updates the target voting yield based on the difference between the target and current - * voting Gold fraction. - */ - function _updateTargetVotingYield() internal onlyWhenNotFrozen { - FixidityLib.Fraction memory votingGoldFraction = FixidityLib.wrap(getVotingGoldFraction()); - if (votingGoldFraction.gt(targetVotingGoldFraction)) { - FixidityLib.Fraction memory votingGoldFractionDelta = votingGoldFraction.subtract( - targetVotingGoldFraction - ); - FixidityLib.Fraction memory targetVotingYieldDelta = votingGoldFractionDelta.multiply( - targetVotingYieldParams.adjustmentFactor - ); - if (targetVotingYieldDelta.gte(targetVotingYieldParams.target)) { - targetVotingYieldParams.target = FixidityLib.newFixed(0); - } else { - targetVotingYieldParams.target = targetVotingYieldParams.target.subtract( - targetVotingYieldDelta - ); - } - } else if (votingGoldFraction.lt(targetVotingGoldFraction)) { - FixidityLib.Fraction memory votingGoldFractionDelta = targetVotingGoldFraction.subtract( - votingGoldFraction - ); - FixidityLib.Fraction memory targetVotingYieldDelta = votingGoldFractionDelta.multiply( - targetVotingYieldParams.adjustmentFactor - ); - targetVotingYieldParams.target = targetVotingYieldParams.target.add(targetVotingYieldDelta); - if (targetVotingYieldParams.target.gt(targetVotingYieldParams.max)) { - targetVotingYieldParams.target = targetVotingYieldParams.max; - } - } - emit TargetVotingYieldUpdated(targetVotingYieldParams.target.unwrap()); - } - - /** - * @notice Updates the target voting yield based on the difference between the target and current - * voting Gold fraction. - * @dev Only called directly by the protocol. - */ - function updateTargetVotingYield() external onlyVm onlyWhenNotFrozen { - _updateTargetVotingYield(); - } - - /** - * @notice Determines if the reserve is low enough to demand a diversion from - * the community reward. Targets initial critical ratio of 2 with a linear - * decline until 25 years have passed where the critical ratio will be 1. - */ - function isReserveLow() external view returns (bool) { - // critical reserve ratio = 2 - time in second / 25 years - FixidityLib.Fraction memory timeSinceInitialization = FixidityLib.newFixed(now.sub(startTime)); - FixidityLib.Fraction memory m = FixidityLib.newFixed(25 * 365 * 1 days); - FixidityLib.Fraction memory b = FixidityLib.newFixed(2); - FixidityLib.Fraction memory criticalRatio; - // Don't let the critical reserve ratio go under 1 after 25 years. - if (timeSinceInitialization.gte(m)) { - criticalRatio = FixidityLib.fixed1(); - } else { - criticalRatio = b.subtract(timeSinceInitialization.divide(m)); - } - FixidityLib.Fraction memory ratio = FixidityLib.wrap(getReserve().getReserveRatio()); - return ratio.lte(criticalRatio); - } - - /** - * @notice Calculates the per validator epoch payment and the total rewards to voters. - * @return The per validator epoch reward. - * @return The total rewards to voters. - * @return The total community reward. - * @return The total carbon offsetting partner reward. - */ - function calculateTargetEpochRewards() - external - view - returns (uint256, uint256, uint256, uint256) - { - uint256 targetVoterReward = getTargetVoterRewards(); - uint256 targetGoldSupplyIncrease = _getTargetGoldSupplyIncrease(); - FixidityLib.Fraction memory rewardsMultiplier = _getRewardsMultiplier(targetGoldSupplyIncrease); - return ( - FixidityLib.newFixed(targetValidatorEpochPayment).multiply(rewardsMultiplier).fromFixed(), - FixidityLib.newFixed(targetVoterReward).multiply(rewardsMultiplier).fromFixed(), - FixidityLib - .newFixed(targetGoldSupplyIncrease) - .multiply(communityRewardFraction) - .multiply(rewardsMultiplier) - .fromFixed(), - FixidityLib - .newFixed(targetGoldSupplyIncrease) - .multiply(carbonOffsettingFraction) - .multiply(rewardsMultiplier) - .fromFixed() - ); - } -} diff --git a/packages/protocol/contracts/governance/Governance.sol b/packages/protocol/contracts/governance/Governance.sol deleted file mode 100644 index f38e2016f..000000000 --- a/packages/protocol/contracts/governance/Governance.sol +++ /dev/null @@ -1,1626 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; -import "openzeppelin-solidity/contracts/math/Math.sol"; -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "openzeppelin-solidity/contracts/utils/Address.sol"; - -import "./interfaces/IGovernance.sol"; -import "./Proposals.sol"; -import "../common/interfaces/IAccounts.sol"; -import "../common/ExtractFunctionSignature.sol"; -import "../common/Initializable.sol"; -import "../common/FixidityLib.sol"; -import "../common/linkedlists/IntegerSortedLinkedList.sol"; -import "../common/UsingRegistry.sol"; -import "../common/UsingPrecompiles.sol"; -import "../common/interfaces/ICeloVersionedContract.sol"; -import "../common/libraries/ReentrancyGuard.sol"; - -/** - * @title A contract for making, passing, and executing on-chain governance proposals. - */ -contract Governance is - IGovernance, - ICeloVersionedContract, - Ownable, - Initializable, - ReentrancyGuard, - UsingRegistry, - UsingPrecompiles -{ - using Proposals for Proposals.Proposal; - using FixidityLib for FixidityLib.Fraction; - using SafeMath for uint256; - using IntegerSortedLinkedList for SortedLinkedList.List; - using BytesLib for bytes; - using Address for address payable; // prettier-ignore - - uint256 private constant FIXED_HALF = 500000000000000000000000; - - enum VoteValue { None, Abstain, No, Yes } - - struct UpvoteRecord { - uint256 proposalId; - uint256 weight; - } - - struct VoteRecord { - Proposals.VoteValue deprecated_value; // obsolete - uint256 proposalId; - uint256 deprecated_weight; // obsolete - uint256 yesVotes; - uint256 noVotes; - uint256 abstainVotes; - } - - struct Voter { - // Key of the proposal voted for in the proposal queue - UpvoteRecord upvote; - uint256 mostRecentReferendumProposal; - // Maps a `dequeued` index to a voter's vote record. - mapping(uint256 => VoteRecord) referendumVotes; - } - - struct ContractConstitution { - FixidityLib.Fraction defaultThreshold; - // Maps a function ID to a corresponding threshold, overriding the default. - mapping(bytes4 => FixidityLib.Fraction) functionThresholds; - } - - struct HotfixRecord { - bool executed; - bool approved; - uint256 preparedEpoch; - mapping(address => bool) whitelisted; - } - - // The baseline is updated as - // max{floor, (1 - baselineUpdateFactor) * baseline + baselineUpdateFactor * participation} - struct ParticipationParameters { - // The average network participation in governance, weighted toward recent proposals. - FixidityLib.Fraction baseline; - // The lower bound on the participation baseline. - FixidityLib.Fraction baselineFloor; - // The weight of the most recent proposal's participation on the baseline. - FixidityLib.Fraction baselineUpdateFactor; - // The proportion of the baseline that constitutes quorum. - FixidityLib.Fraction baselineQuorumFactor; - } - - Proposals.StageDurations public stageDurations; - uint256 public queueExpiry; - uint256 public dequeueFrequency; - address public approver; - uint256 public lastDequeue; - uint256 public concurrentProposals; - uint256 public proposalCount; - uint256 public minDeposit; - mapping(address => uint256) public refundedDeposits; - mapping(address => ContractConstitution) private constitution; - mapping(uint256 => Proposals.Proposal) private proposals; - mapping(address => Voter) internal voters; - mapping(bytes32 => HotfixRecord) public hotfixes; - SortedLinkedList.List private queue; - uint256[] public dequeued; - uint256[] public emptyIndices; - ParticipationParameters private participationParameters; - - event ApproverSet(address indexed approver); - - event ConcurrentProposalsSet(uint256 concurrentProposals); - - event MinDepositSet(uint256 minDeposit); - - event QueueExpirySet(uint256 queueExpiry); - - event DequeueFrequencySet(uint256 dequeueFrequency); - - event ReferendumStageDurationSet(uint256 referendumStageDuration); - - event ExecutionStageDurationSet(uint256 executionStageDuration); - - event ConstitutionSet(address indexed destination, bytes4 indexed functionId, uint256 threshold); - - event ProposalQueued( - uint256 indexed proposalId, - address indexed proposer, - uint256 transactionCount, - uint256 deposit, - uint256 timestamp - ); - - event ProposalUpvoted(uint256 indexed proposalId, address indexed account, uint256 upvotes); - - event ProposalUpvoteRevoked( - uint256 indexed proposalId, - address indexed account, - uint256 revokedUpvotes - ); - - event ProposalDequeued(uint256 indexed proposalId, uint256 timestamp); - - event ProposalApproved(uint256 indexed proposalId); - - event ProposalVoted( - uint256 indexed proposalId, - address indexed account, - uint256 value, - uint256 weight - ); - - event ProposalVotedV2( - uint256 indexed proposalId, - address indexed account, - uint256 yesVotes, - uint256 noVotes, - uint256 abstainVotes - ); - - event ProposalVoteRevoked( - uint256 indexed proposalId, - address indexed account, - uint256 value, - uint256 weight - ); - - event ProposalVoteRevokedV2( - uint256 indexed proposalId, - address indexed account, - uint256 yesVotes, - uint256 noVotes, - uint256 abstainVotes - ); - - event ProposalExecuted(uint256 indexed proposalId); - - event ProposalExpired(uint256 indexed proposalId); - - event ParticipationBaselineUpdated(uint256 participationBaseline); - - event ParticipationFloorSet(uint256 participationFloor); - - event ParticipationBaselineUpdateFactorSet(uint256 baselineUpdateFactor); - - event ParticipationBaselineQuorumFactorSet(uint256 baselineQuorumFactor); - - event HotfixWhitelisted(bytes32 indexed hash, address whitelister); - - event HotfixApproved(bytes32 indexed hash); - - event HotfixPrepared(bytes32 indexed hash, uint256 indexed epoch); - - event HotfixExecuted(bytes32 indexed hash); - - modifier hotfixNotExecuted(bytes32 hash) { - require(!hotfixes[hash].executed, "hotfix already executed"); - _; - } - - modifier onlyApprover() { - require(msg.sender == approver, "msg.sender not approver"); - _; - } - - modifier onlyLockedGold() { - require(msg.sender == address(getLockedGold()), "msg.sender not lockedGold"); - _; - } - - /** - * @notice Sets initialized == true on implementation contracts - * @param test Set to true to skip implementation initialization - */ - constructor(bool test) public Initializable(test) {} - - function() external payable { - require(msg.data.length == 0, "unknown method"); - } - - /** - * @notice Returns the storage, major, minor, and patch version of the contract. - * @return Storage version of the contract. - * @return Major version of the contract. - * @return Minor version of the contract. - * @return Patch version of the contract. - */ - function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { - return (1, 4, 0, 0); - } - - /** - * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. - * @param registryAddress The address of the registry contract. - * @param _approver The address that needs to approve proposals to move to the referendum stage. - * @param _concurrentProposals The number of proposals to dequeue at once. - * @param _minDeposit The minimum CELO deposit needed to make a proposal. - * @param _queueExpiry The number of seconds a proposal can stay in the queue before expiring. - * @param _dequeueFrequency The number of seconds before the next batch of proposals can be - * dequeued. - * @param referendumStageDuration The number of seconds users have to vote on a dequeued proposal - * after the approval stage ends. - * @param executionStageDuration The number of seconds users have to execute a passed proposal - * after the referendum stage ends. - * @param participationBaseline The initial value of the participation baseline. - * @param participationFloor The participation floor. - * @param baselineUpdateFactor The weight of the new participation in the baseline update rule. - * @param baselineQuorumFactor The proportion of the baseline that constitutes quorum. - * @dev Should be called only once. - */ - function initialize( - address registryAddress, - address _approver, - uint256 _concurrentProposals, - uint256 _minDeposit, - uint256 _queueExpiry, - uint256 _dequeueFrequency, - uint256 referendumStageDuration, - uint256 executionStageDuration, - uint256 participationBaseline, - uint256 participationFloor, - uint256 baselineUpdateFactor, - uint256 baselineQuorumFactor - ) external initializer { - _transferOwnership(msg.sender); - setRegistry(registryAddress); - setApprover(_approver); - setConcurrentProposals(_concurrentProposals); - setMinDeposit(_minDeposit); - setQueueExpiry(_queueExpiry); - setDequeueFrequency(_dequeueFrequency); - setReferendumStageDuration(referendumStageDuration); - setExecutionStageDuration(executionStageDuration); - setParticipationBaseline(participationBaseline); - setParticipationFloor(participationFloor); - setBaselineUpdateFactor(baselineUpdateFactor); - setBaselineQuorumFactor(baselineQuorumFactor); - // solhint-disable-next-line not-rely-on-time - lastDequeue = now; - } - - /** - * @notice Updates the address that has permission to approve proposals in the approval stage. - * @param _approver The address that has permission to approve proposals in the approval stage. - */ - function setApprover(address _approver) public onlyOwner { - require(_approver != address(0), "Approver cannot be 0"); - require(_approver != approver, "Approver unchanged"); - approver = _approver; - emit ApproverSet(_approver); - } - - /** - * @notice Updates the number of proposals to dequeue at a time. - * @param _concurrentProposals The number of proposals to dequeue at at a time. - */ - function setConcurrentProposals(uint256 _concurrentProposals) public onlyOwner { - require(_concurrentProposals != 0, "Number of proposals must be larger than zero"); - require(_concurrentProposals != concurrentProposals, "Number of proposals unchanged"); - concurrentProposals = _concurrentProposals; - emit ConcurrentProposalsSet(_concurrentProposals); - } - - /** - * @notice Updates the minimum deposit needed to make a proposal. - * @param _minDeposit The minimum CELO deposit needed to make a proposal. - */ - function setMinDeposit(uint256 _minDeposit) public onlyOwner { - require(_minDeposit != 0, "minDeposit must be larger than 0"); - require(_minDeposit != minDeposit, "Minimum deposit unchanged"); - minDeposit = _minDeposit; - emit MinDepositSet(_minDeposit); - } - - /** - * @notice Updates the number of seconds before a queued proposal expires. - * @param _queueExpiry The number of seconds a proposal can stay in the queue before expiring. - */ - function setQueueExpiry(uint256 _queueExpiry) public onlyOwner { - require(_queueExpiry != 0, "QueueExpiry must be larger than 0"); - require(_queueExpiry != queueExpiry, "QueueExpiry unchanged"); - queueExpiry = _queueExpiry; - emit QueueExpirySet(_queueExpiry); - } - - /** - * @notice Updates the minimum number of seconds before the next batch of proposals can be - * dequeued. - * @param _dequeueFrequency The number of seconds before the next batch of proposals can be - * dequeued. - */ - function setDequeueFrequency(uint256 _dequeueFrequency) public onlyOwner { - require(_dequeueFrequency != 0, "dequeueFrequency must be larger than 0"); - require(_dequeueFrequency != dequeueFrequency, "dequeueFrequency unchanged"); - dequeueFrequency = _dequeueFrequency; - emit DequeueFrequencySet(_dequeueFrequency); - } - - /** - * @notice Updates the number of seconds proposals stay in the referendum stage. - * @param referendumStageDuration The number of seconds proposals stay in the referendum stage. - */ - function setReferendumStageDuration(uint256 referendumStageDuration) public onlyOwner { - require(referendumStageDuration != 0, "Duration must be larger than 0"); - require(referendumStageDuration != stageDurations.referendum, "Duration unchanged"); - stageDurations.referendum = referendumStageDuration; - emit ReferendumStageDurationSet(referendumStageDuration); - } - - /** - * @notice Updates the number of seconds proposals stay in the execution stage. - * @param executionStageDuration The number of seconds proposals stay in the execution stage. - */ - function setExecutionStageDuration(uint256 executionStageDuration) public onlyOwner { - require(executionStageDuration != 0, "Duration must be larger than 0"); - require(executionStageDuration != stageDurations.execution, "Duration unchanged"); - stageDurations.execution = executionStageDuration; - emit ExecutionStageDurationSet(executionStageDuration); - } - - /** - * @notice Updates the participation baseline. - * @param participationBaseline The value of the baseline. - */ - function setParticipationBaseline(uint256 participationBaseline) public onlyOwner { - FixidityLib.Fraction memory participationBaselineFrac = FixidityLib.wrap(participationBaseline); - require( - FixidityLib.isProperFraction(participationBaselineFrac), - "Participation baseline greater than one" - ); - require( - !participationBaselineFrac.equals(participationParameters.baseline), - "Participation baseline unchanged" - ); - participationParameters.baseline = participationBaselineFrac; - emit ParticipationBaselineUpdated(participationBaseline); - } - - /** - * @notice Updates the floor of the participation baseline. - * @param participationFloor The value at which the baseline is floored. - */ - function setParticipationFloor(uint256 participationFloor) public onlyOwner { - FixidityLib.Fraction memory participationFloorFrac = FixidityLib.wrap(participationFloor); - require( - FixidityLib.isProperFraction(participationFloorFrac), - "Participation floor greater than one" - ); - require( - !participationFloorFrac.equals(participationParameters.baselineFloor), - "Participation baseline floor unchanged" - ); - participationParameters.baselineFloor = participationFloorFrac; - emit ParticipationFloorSet(participationFloor); - } - - /** - * @notice Updates the weight of the new participation in the baseline update rule. - * @param baselineUpdateFactor The new baseline update factor. - */ - function setBaselineUpdateFactor(uint256 baselineUpdateFactor) public onlyOwner { - FixidityLib.Fraction memory baselineUpdateFactorFrac = FixidityLib.wrap(baselineUpdateFactor); - require( - FixidityLib.isProperFraction(baselineUpdateFactorFrac), - "Baseline update factor greater than one" - ); - require( - !baselineUpdateFactorFrac.equals(participationParameters.baselineUpdateFactor), - "Baseline update factor unchanged" - ); - participationParameters.baselineUpdateFactor = baselineUpdateFactorFrac; - emit ParticipationBaselineUpdateFactorSet(baselineUpdateFactor); - } - - /** - * @notice Updates the proportion of the baseline that constitutes quorum. - * @param baselineQuorumFactor The new baseline quorum factor. - */ - function setBaselineQuorumFactor(uint256 baselineQuorumFactor) public onlyOwner { - FixidityLib.Fraction memory baselineQuorumFactorFrac = FixidityLib.wrap(baselineQuorumFactor); - require( - FixidityLib.isProperFraction(baselineQuorumFactorFrac), - "Baseline quorum factor greater than one" - ); - require( - !baselineQuorumFactorFrac.equals(participationParameters.baselineQuorumFactor), - "Baseline quorum factor unchanged" - ); - participationParameters.baselineQuorumFactor = baselineQuorumFactorFrac; - emit ParticipationBaselineQuorumFactorSet(baselineQuorumFactor); - } - - /** - * @notice Updates the ratio of yes:yes+no votes needed for a specific class of proposals to pass. - * @param destination The destination of proposals for which this threshold should apply. - * @param functionId The function ID of proposals for which this threshold should apply. Zero - * will set the default. - * @param threshold The threshold. - * @dev If no constitution is explicitly set the default is a simple majority, i.e. 1:2. - */ - function setConstitution(address destination, bytes4 functionId, uint256 threshold) - external - onlyOwner - { - require(destination != address(0), "Destination cannot be zero"); - require( - threshold > FIXED_HALF && threshold <= FixidityLib.fixed1().unwrap(), - "Threshold has to be greater than majority and not greater than unanimity" - ); - if (functionId == 0) { - constitution[destination].defaultThreshold = FixidityLib.wrap(threshold); - } else { - constitution[destination].functionThresholds[functionId] = FixidityLib.wrap(threshold); - } - emit ConstitutionSet(destination, functionId, threshold); - } - - /** - * @notice Creates a new proposal and adds it to end of the queue with no upvotes. - * @param values The values of CELO to be sent in the proposed transactions. - * @param destinations The destination addresses of the proposed transactions. - * @param data The concatenated data to be included in the proposed transactions. - * @param dataLengths The lengths of each transaction's data. - * @return The ID of the newly proposed proposal. - * @dev The minimum deposit must be included with the proposal, returned if/when the proposal is - * dequeued. - */ - function propose( - uint256[] calldata values, - address[] calldata destinations, - bytes calldata data, - uint256[] calldata dataLengths, - string calldata descriptionUrl - ) external payable returns (uint256) { - dequeueProposalsIfReady(); - require(msg.value >= minDeposit, "Too small deposit"); - - proposalCount = proposalCount.add(1); - Proposals.Proposal storage proposal = proposals[proposalCount]; - proposal.make(values, destinations, data, dataLengths, msg.sender, msg.value); - proposal.setDescriptionUrl(descriptionUrl); - queue.push(proposalCount); - // solhint-disable-next-line not-rely-on-time - emit ProposalQueued(proposalCount, msg.sender, proposal.transactions.length, msg.value, now); - return proposalCount; - } - - /** - * @notice Removes a proposal if it is queued and expired. - * @param proposalId The ID of the proposal to remove. - * @return Whether the proposal was removed. - */ - function removeIfQueuedAndExpired(uint256 proposalId) private returns (bool) { - if (isQueued(proposalId) && isQueuedProposalExpired(proposalId)) { - queue.remove(proposalId); - emit ProposalExpired(proposalId); - return true; - } - return false; - } - - /** - * @notice Requires a proposal is dequeued and removes it if expired. - * @param proposalId The ID of the proposal. - * @return The proposal storage struct corresponding to `proposalId`. - * @return The proposal stage corresponding to `proposalId`. - */ - function requireDequeuedAndDeleteExpired(uint256 proposalId, uint256 index) - private - returns (Proposals.Proposal storage, Proposals.Stage) - { - Proposals.Proposal storage proposal = proposals[proposalId]; - require(_isDequeuedProposal(proposal, proposalId, index), "Proposal not dequeued"); - Proposals.Stage stage = getProposalDequeuedStage(proposal); - if (_isDequeuedProposalExpired(proposal, stage)) { - deleteDequeuedProposal(proposal, proposalId, index); - return (proposal, Proposals.Stage.Expiration); - } - return (proposal, stage); - } - - /** - * @notice Upvotes a queued proposal. - * @param proposalId The ID of the proposal to upvote. - * @param lesser The ID of the proposal that will be just behind `proposalId` in the queue. - * @param greater The ID of the proposal that will be just ahead `proposalId` in the queue. - * @return Whether or not the upvote was made successfully. - * @dev Provide 0 for `lesser`/`greater` when the proposal will be at the tail/head of the queue. - * @dev Reverts if the account has already upvoted a proposal in the queue. - */ - function upvote(uint256 proposalId, uint256 lesser, uint256 greater) - external - nonReentrant - returns (bool) - { - dequeueProposalsIfReady(); - // If acting on an expired proposal, expire the proposal and take no action. - if (removeIfQueuedAndExpired(proposalId)) { - return false; - } - - address account = getAccounts().voteSignerToAccount(msg.sender); - Voter storage voter = voters[account]; - removeIfQueuedAndExpired(voter.upvote.proposalId); - - // We can upvote a proposal in the queue if we're not already upvoting a proposal in the queue. - uint256 weight = getLockedGold().getAccountTotalLockedGold(account); - require(weight > 0, "cannot upvote without locking gold"); - require(queue.contains(proposalId), "cannot upvote a proposal not in the queue"); - require( - voter.upvote.proposalId == 0 || !queue.contains(voter.upvote.proposalId), - "cannot upvote more than one queued proposal" - ); - uint256 upvotes = queue.getValue(proposalId).add(weight); - queue.update(proposalId, upvotes, lesser, greater); - voter.upvote = UpvoteRecord(proposalId, weight); - emit ProposalUpvoted(proposalId, account, weight); - return true; - } - - /** - * @notice Returns stage of governance process given proposal is in - * @param proposalId The ID of the proposal to query. - * @return proposal stage - */ - function getProposalStage(uint256 proposalId) external view returns (Proposals.Stage) { - if (proposalId == 0 || proposalId > proposalCount) { - return Proposals.Stage.None; - } - Proposals.Proposal storage proposal = proposals[proposalId]; - if (isQueued(proposalId)) { - return - _isQueuedProposalExpired(proposal) ? Proposals.Stage.Expiration : Proposals.Stage.Queued; - } else { - Proposals.Stage stage = getProposalDequeuedStage(proposal); - return _isDequeuedProposalExpired(proposal, stage) ? Proposals.Stage.Expiration : stage; - } - } - - /** - * @notice Revokes an upvote on a queued proposal. - * @param lesser The ID of the proposal that will be just behind the previously upvoted proposal - * in the queue. - * @param greater The ID of the proposal that will be just ahead of the previously upvoted - * proposal in the queue. - * @return Whether or not the upvote was revoked successfully. - * @dev Provide 0 for `lesser`/`greater` when the proposal will be at the tail/head of the queue. - */ - function revokeUpvote(uint256 lesser, uint256 greater) external nonReentrant returns (bool) { - dequeueProposalsIfReady(); - address account = getAccounts().voteSignerToAccount(msg.sender); - Voter storage voter = voters[account]; - uint256 proposalId = voter.upvote.proposalId; - require(proposalId != 0, "Account has no historical upvote"); - removeIfQueuedAndExpired(proposalId); - if (queue.contains(proposalId)) { - queue.update( - proposalId, - queue.getValue(proposalId).sub(voter.upvote.weight), - lesser, - greater - ); - emit ProposalUpvoteRevoked(proposalId, account, voter.upvote.weight); - } - voter.upvote = UpvoteRecord(0, 0); - return true; - } - - /** - * @notice Approves a proposal in the approval stage. - * @param proposalId The ID of the proposal to approve. - * @param index The index of the proposal ID in `dequeued`. - * @return Whether or not the approval was made successfully. - */ - function approve(uint256 proposalId, uint256 index) external onlyApprover returns (bool) { - dequeueProposalsIfReady(); - (Proposals.Proposal storage proposal, Proposals.Stage stage) = requireDequeuedAndDeleteExpired( - proposalId, - index - ); - if (!proposal.exists()) { - return false; - } - - require(!proposal.isApproved(), "Proposal already approved"); - require( - stage == Proposals.Stage.Referendum || stage == Proposals.Stage.Execution, - "Proposal not in correct stage" - ); - proposal.approved = true; - // Ensures networkWeight is set by the end of the Referendum stage, even if 0 votes are cast. - proposal.networkWeight = getLockedGold().getTotalLockedGold(); - emit ProposalApproved(proposalId); - return true; - } - - /** - * @notice Votes on a proposal in the referendum stage. - * @param proposalId The ID of the proposal to vote on. - * @param index The index of the proposal ID in `dequeued`. - * @param value Whether to vote yes, no, or abstain. - * @return Whether or not the vote was cast successfully. - */ - /* solhint-disable code-complexity */ - function vote(uint256 proposalId, uint256 index, Proposals.VoteValue value) - external - nonReentrant - returns (bool) - { - dequeueProposalsIfReady(); - (Proposals.Proposal storage proposal, Proposals.Stage stage) = requireDequeuedAndDeleteExpired( - proposalId, - index - ); - if (!proposal.exists()) { - return false; - } - - require(stage == Proposals.Stage.Referendum, "Incorrect proposal state"); - require(value != Proposals.VoteValue.None, "Vote value unset"); - - address account = getAccounts().voteSignerToAccount(msg.sender); - uint256 weight = getLockedGold().getAccountTotalGovernanceVotingPower(account); - require(weight != 0, "Voter weight zero"); - - _vote( - proposal, - proposalId, - index, - account, - value == Proposals.VoteValue.Yes ? weight : 0, - value == Proposals.VoteValue.No ? weight : 0, - value == Proposals.VoteValue.Abstain ? weight : 0 - ); - return true; - } - - /** - * @notice Votes partially on a proposal in the referendum stage. - * @param proposalId The ID of the proposal to vote on. - * @param index The index of the proposal ID in `dequeued`. - * @param yesVotes The yes votes weight. - * @param noVotes The no votes weight. - * @param abstainVotes The abstain votes weight. - * @return Whether or not the vote was cast successfully. - */ - /* solhint-disable code-complexity */ - function votePartially( - uint256 proposalId, - uint256 index, - uint256 yesVotes, - uint256 noVotes, - uint256 abstainVotes - ) external nonReentrant returns (bool) { - dequeueProposalsIfReady(); - (Proposals.Proposal storage proposal, Proposals.Stage stage) = requireDequeuedAndDeleteExpired( - proposalId, - index - ); - if (!proposal.exists()) { - return false; - } - - require(stage == Proposals.Stage.Referendum, "Incorrect proposal state"); - - address account = getAccounts().voteSignerToAccount(msg.sender); - uint256 totalVotingPower = getLockedGold().getAccountTotalGovernanceVotingPower(account); - - require( - totalVotingPower >= yesVotes.add(noVotes).add(abstainVotes), - "Voter doesn't have enough locked Celo (formerly known as Celo Gold)" - ); - _vote(proposal, proposalId, index, account, yesVotes, noVotes, abstainVotes); - - return true; - } - - /** - * @notice Votes on a proposal in the referendum stage. - * @param proposal The proposal struct. - * @param proposalId The ID of the proposal to vote on. - * @param index The index of the proposal ID in `dequeued`. - * @param account Account based on signer. - * @param yesVotes The yes votes weight. - * @param noVotes The no votes weight. - * @param abstainVotes The abstain votes weight. - * @return Whether or not the proposal is passing. - */ - function _vote( - Proposals.Proposal storage proposal, - uint256 proposalId, - uint256 index, - address account, - uint256 yesVotes, - uint256 noVotes, - uint256 abstainVotes - ) private { - Voter storage voter = voters[account]; - - VoteRecord storage previousVoteRecord = voter.referendumVotes[index]; - - if (previousVoteRecord.proposalId != proposalId) { - // VoteRecord is being stored based on index (in `dequeued`) rather than proposalId. - // It can happen that user voted on proposal that later gets deleted. - // VoteRecord will still stay in `referendumVotes` mapping. - // Once new proposal is created it might get same index as previous proposal. - // In such case we need to check whether existing VoteRecord is relevant to new - // proposal of whether it is just left over data. - proposal.updateVote(0, 0, 0, yesVotes, noVotes, abstainVotes); - } else if (previousVoteRecord.deprecated_weight != 0) { - // backward compatibility for transition period - this should be deleted later on - proposal.updateVote( - previousVoteRecord.deprecated_value == Proposals.VoteValue.Yes - ? previousVoteRecord.deprecated_weight - : 0, - previousVoteRecord.deprecated_value == Proposals.VoteValue.No - ? previousVoteRecord.deprecated_weight - : 0, - previousVoteRecord.deprecated_value == Proposals.VoteValue.Abstain - ? previousVoteRecord.deprecated_weight - : 0, - yesVotes, - noVotes, - abstainVotes - ); - - } else { - proposal.updateVote( - previousVoteRecord.yesVotes, - previousVoteRecord.noVotes, - previousVoteRecord.abstainVotes, - yesVotes, - noVotes, - abstainVotes - ); - } - - proposal.networkWeight = getLockedGold().getTotalLockedGold(); - voter.referendumVotes[index] = VoteRecord( - Proposals.VoteValue.None, - proposalId, - 0, - yesVotes, - noVotes, - abstainVotes - ); - if (proposal.timestamp > proposals[voter.mostRecentReferendumProposal].timestamp) { - voter.mostRecentReferendumProposal = proposalId; - } - - emit ProposalVotedV2(proposalId, account, yesVotes, noVotes, abstainVotes); - } - - /* solhint-enable code-complexity */ - - /** - * @notice Revoke votes on all proposals of sender in the referendum stage. - * @return Whether or not all votes of an account were successfully revoked. - */ - function revokeVotes() external nonReentrant returns (bool) { - address account = getAccounts().voteSignerToAccount(msg.sender); - Voter storage voter = voters[account]; - for ( - uint256 dequeueIndex = 0; - dequeueIndex < dequeued.length; - dequeueIndex = dequeueIndex.add(1) - ) { - VoteRecord storage voteRecord = voter.referendumVotes[dequeueIndex]; - - // Skip proposals where there was no vote cast by the user AND - // ensure vote record proposal matches identifier of dequeued index proposal. - if ( - voteRecord.proposalId == dequeued[dequeueIndex] && - (voteRecord.yesVotes != 0 || - voteRecord.noVotes != 0 || - voteRecord.abstainVotes != 0 || - voteRecord.deprecated_weight != 0) - ) { - (Proposals.Proposal storage proposal, Proposals.Stage stage) = - requireDequeuedAndDeleteExpired(voteRecord.proposalId, dequeueIndex); // prettier-ignore - - // only revoke from proposals which are still in referendum - if (stage == Proposals.Stage.Referendum) { - if (voteRecord.deprecated_weight != 0) { - // backward compatibility for transition period - this should be deleted later on - uint256 previousYes = voteRecord.deprecated_value == Proposals.VoteValue.Yes - ? voteRecord.deprecated_weight - : 0; - uint256 previousNo = voteRecord.deprecated_value == Proposals.VoteValue.No - ? voteRecord.deprecated_weight - : 0; - uint256 previousAbstain = voteRecord.deprecated_value == Proposals.VoteValue.Abstain - ? voteRecord.deprecated_weight - : 0; - proposal.updateVote(previousYes, previousNo, previousAbstain, 0, 0, 0); - - proposal.networkWeight = getLockedGold().getTotalLockedGold(); - emit ProposalVoteRevokedV2( - voteRecord.proposalId, - account, - previousYes, - previousNo, - previousAbstain - ); - } else { - proposal.updateVote( - voteRecord.yesVotes, - voteRecord.noVotes, - voteRecord.abstainVotes, - 0, - 0, - 0 - ); - proposal.networkWeight = getLockedGold().getTotalLockedGold(); - emit ProposalVoteRevokedV2( - voteRecord.proposalId, - account, - voteRecord.yesVotes, - voteRecord.noVotes, - voteRecord.abstainVotes - ); - } - } - - // always delete dequeue vote records for gas refund as they must be expired or revoked - delete voter.referendumVotes[dequeueIndex]; - } - } - - // reset most recent referendum proposal ID to guarantee isVotingReferendum == false - voter.mostRecentReferendumProposal = 0; - return true; - } - - /** - * @notice Executes a proposal in the execution stage, removing it from `dequeued`. - * @param proposalId The ID of the proposal to vote on. - * @param index The index of the proposal ID in `dequeued`. - * @return Whether or not the proposal was executed successfully. - * @dev Does not remove the proposal if the execution fails. - */ - function execute(uint256 proposalId, uint256 index) external nonReentrant returns (bool) { - dequeueProposalsIfReady(); - (Proposals.Proposal storage proposal, Proposals.Stage stage) = requireDequeuedAndDeleteExpired( - proposalId, - index - ); - bool notExpired = proposal.exists(); - if (notExpired) { - require(proposal.isApproved(), "Proposal not approved"); - require( - stage == Proposals.Stage.Execution && _isProposalPassing(proposal), - "Proposal not in execution stage or not passing" - ); - proposal.execute(); - emit ProposalExecuted(proposalId); - deleteDequeuedProposal(proposal, proposalId, index); - } - return notExpired; - } - - /** - * @notice Approves the hash of a hotfix transaction(s). - * @param hash The abi encoded keccak256 hash of the hotfix transaction(s) to be approved. - */ - function approveHotfix(bytes32 hash) external hotfixNotExecuted(hash) onlyApprover { - hotfixes[hash].approved = true; - emit HotfixApproved(hash); - } - - /** - * @notice Returns whether given hotfix hash has been whitelisted by given address. - * @param hash The abi encoded keccak256 hash of the hotfix transaction(s) to be whitelisted. - * @param whitelister Address to check whitelist status of. - */ - function isHotfixWhitelistedBy(bytes32 hash, address whitelister) public view returns (bool) { - return hotfixes[hash].whitelisted[whitelister]; - } - - /** - * @notice Whitelists the hash of a hotfix transaction(s). - * @param hash The abi encoded keccak256 hash of the hotfix transaction(s) to be whitelisted. - */ - function whitelistHotfix(bytes32 hash) external hotfixNotExecuted(hash) { - hotfixes[hash].whitelisted[msg.sender] = true; - emit HotfixWhitelisted(hash, msg.sender); - } - - /** - * @notice Gives hotfix a prepared epoch for execution. - * @param hash The hash of the hotfix to be prepared. - */ - function prepareHotfix(bytes32 hash) external hotfixNotExecuted(hash) { - require(isHotfixPassing(hash), "hotfix not whitelisted by 2f+1 validators"); - uint256 epoch = getEpochNumber(); - require(hotfixes[hash].preparedEpoch < epoch, "hotfix already prepared for this epoch"); - hotfixes[hash].preparedEpoch = epoch; - emit HotfixPrepared(hash, epoch); - } - - /** - * @notice Executes a whitelisted proposal. - * @param values The values of CELO to be sent in the proposed transactions. - * @param destinations The destination addresses of the proposed transactions. - * @param data The concatenated data to be included in the proposed transactions. - * @param dataLengths The lengths of each transaction's data. - * @param salt Arbitrary salt associated with hotfix which guarantees uniqueness of hash. - * @dev Reverts if hotfix is already executed, not approved, or not prepared for current epoch. - */ - function executeHotfix( - uint256[] calldata values, - address[] calldata destinations, - bytes calldata data, - uint256[] calldata dataLengths, - bytes32 salt - ) external { - bytes32 hash = keccak256(abi.encode(values, destinations, data, dataLengths, salt)); - - (bool approved, bool executed, uint256 preparedEpoch) = getHotfixRecord(hash); - require(!executed, "hotfix already executed"); - require(approved, "hotfix not approved"); - require(preparedEpoch == getEpochNumber(), "hotfix must be prepared for this epoch"); - - Proposals.makeMem(values, destinations, data, dataLengths, msg.sender, 0).executeMem(); - - hotfixes[hash].executed = true; - emit HotfixExecuted(hash); - } - - /** - * @notice Withdraws refunded CELO deposits. - * @return Whether or not the withdraw was successful. - */ - function withdraw() external nonReentrant returns (bool) { - uint256 value = refundedDeposits[msg.sender]; - require(value != 0, "Nothing to withdraw"); - require(value <= address(this).balance, "Inconsistent balance"); - refundedDeposits[msg.sender] = 0; - msg.sender.sendValue(value); - return true; - } - - /** - * @notice Returns whether or not a particular account is voting on proposals. - * @param account The address of the account. - * @return Whether or not the account is voting on proposals. - */ - function isVoting(address account) external view returns (bool) { - Voter storage voter = voters[account]; - uint256 upvotedProposal = voter.upvote.proposalId; - bool isVotingQueue = upvotedProposal != 0 && - isQueued(upvotedProposal) && - !isQueuedProposalExpired(upvotedProposal); - Proposals.Proposal storage proposal = proposals[voter.mostRecentReferendumProposal]; - bool isVotingReferendum = (getProposalDequeuedStage(proposal) == Proposals.Stage.Referendum); - return isVotingQueue || isVotingReferendum; - } - - /** - * @notice Returns the number of seconds proposals stay in the referendum stage. - * @return The number of seconds proposals stay in the referendum stage. - */ - function getReferendumStageDuration() external view returns (uint256) { - return stageDurations.referendum; - } - - /** - * @notice Returns the number of seconds proposals stay in the execution stage. - * @return The number of seconds proposals stay in the execution stage. - */ - function getExecutionStageDuration() external view returns (uint256) { - return stageDurations.execution; - } - - /** - * @notice Returns the participation parameters. - * @return baseline The participation baseline parameter. - * @return baselineFloor The participation baseline floor parameter. - * @return baselineUpdateFactor The participation baseline update factor parameter. - * @return baselineQuorumFactor The participation baseline quorum factor parameter. - */ - function getParticipationParameters() external view returns (uint256, uint256, uint256, uint256) { - return ( - participationParameters.baseline.unwrap(), - participationParameters.baselineFloor.unwrap(), - participationParameters.baselineUpdateFactor.unwrap(), - participationParameters.baselineQuorumFactor.unwrap() - ); - } - - /** - * @notice Returns whether or not a proposal exists. - * @param proposalId The ID of the proposal. - * @return Whether or not the proposal exists. - */ - function proposalExists(uint256 proposalId) external view returns (bool) { - return proposals[proposalId].exists(); - } - - /** - * @notice Returns an unpacked proposal struct with its transaction count. - * @param proposalId The ID of the proposal to unpack. - * @return proposer - * @return deposit - * @return timestamp - * @return transaction Transaction count. - * @return description Description url. - */ - function getProposal(uint256 proposalId) - external - view - returns (address, uint256, uint256, uint256, string memory, uint256, bool) - { - return proposals[proposalId].unpack(); - } - - /** - * @notice Returns a specified transaction in a proposal. - * @param proposalId The ID of the proposal to query. - * @param index The index of the specified transaction in the proposal's transaction list. - * @return value Transaction value. - * @return destination Transaction destination. - * @return data Transaction data. - */ - function getProposalTransaction(uint256 proposalId, uint256 index) - external - view - returns (uint256, address, bytes memory) - { - return proposals[proposalId].getTransaction(index); - } - - /** - * @notice Returns whether or not a proposal has been approved. - * @param proposalId The ID of the proposal. - * @return Whether or not the proposal has been approved. - */ - function isApproved(uint256 proposalId) external view returns (bool) { - return proposals[proposalId].isApproved(); - } - - /** - * @notice Returns the referendum vote totals for a proposal. - * @param proposalId The ID of the proposal. - * @return yes The yes vote totals. - * @return no The no vote totals. - * @return abstain The abstain vote totals. - */ - function getVoteTotals(uint256 proposalId) external view returns (uint256, uint256, uint256) { - return proposals[proposalId].getVoteTotals(); - } - - /** - * @notice Returns an accounts vote record on a particular index in `dequeued`. - * @param account The address of the account to get the record for. - * @param index The index in `dequeued`. - * @return The corresponding proposal ID, vote value, and weight. - * @return The depreciated vote value. - * @return The deprecieated weight. - * @return The yes weight. - * @return The no weight. - * @return The abstain weight. - */ - function getVoteRecord(address account, uint256 index) - external - view - returns (uint256, uint256, uint256, uint256, uint256, uint256) - { - VoteRecord storage record = voters[account].referendumVotes[index]; - return ( - record.proposalId, - uint256(record.deprecated_value), - record.deprecated_weight, - record.yesVotes, - record.noVotes, - record.abstainVotes - ); - } - - /** - * @notice Returns the number of proposals in the queue. - * @return The number of proposals in the queue. - */ - function getQueueLength() external view returns (uint256) { - return queue.list.numElements; - } - - /** - * @notice Returns the number of upvotes the queued proposal has received. - * @param proposalId The ID of the proposal. - * @return The number of upvotes a queued proposal has received. - */ - function getUpvotes(uint256 proposalId) external view returns (uint256) { - require(isQueued(proposalId), "Proposal not queued"); - return queue.getValue(proposalId); - } - - /** - * @notice Returns the proposal ID and upvote total for all queued proposals. - * @return proposalID The proposal ID for all queued proposals. - * @return total The upvote total for all queued proposals. - * @dev Note that this includes expired proposals that have yet to be removed from the queue. - */ - function getQueue() external view returns (uint256[] memory, uint256[] memory) { - return queue.getElements(); - } - - /** - * @notice Returns the dequeued proposal IDs. - * @return The dequeued proposal IDs. - * @dev Note that this includes unused indices with proposalId == 0 from deleted proposals. - */ - function getDequeue() external view returns (uint256[] memory) { - return dequeued; - } - - /** - * @notice Returns the ID of the proposal upvoted by `account` and the weight of that upvote. - * @param account The address of the account. - * @return The ID of the proposal upvoted by `account`. - * @return The weight of that upvote. - */ - function getUpvoteRecord(address account) external view returns (uint256, uint256) { - UpvoteRecord memory upvoteRecord = voters[account].upvote; - return (upvoteRecord.proposalId, upvoteRecord.weight); - } - - /** - * @notice Returns the ID of the most recently dequeued proposal voted on by `account`. - * @param account The address of the account. - * @return The ID of the most recently dequeued proposal voted on by `account`.. - */ - function getMostRecentReferendumProposal(address account) external view returns (uint256) { - return voters[account].mostRecentReferendumProposal; - } - - /** - * @notice Returns number of validators from current set which have whitelisted the given hotfix. - * @param hash The abi encoded keccak256 hash of the hotfix transaction. - * @return Whitelist tally - */ - function hotfixWhitelistValidatorTally(bytes32 hash) public view returns (uint256) { - uint256 tally = 0; - uint256 n = numberValidatorsInCurrentSet(); - IAccounts accounts = getAccounts(); - for (uint256 i = 0; i < n; i = i.add(1)) { - address validatorSigner = validatorSignerAddressFromCurrentSet(i); - address validatorAccount = accounts.signerToAccount(validatorSigner); - if ( - isHotfixWhitelistedBy(hash, validatorSigner) || - isHotfixWhitelistedBy(hash, validatorAccount) - ) { - tally = tally.add(1); - } - } - return tally; - } - - /** - * @notice Checks if a byzantine quorum of validators has whitelisted the given hotfix. - * @param hash The abi encoded keccak256 hash of the hotfix transaction. - * @return Whether validator whitelist tally >= validator byzantine quorum - */ - function isHotfixPassing(bytes32 hash) public view returns (bool) { - return hotfixWhitelistValidatorTally(hash) >= minQuorumSizeInCurrentSet(); - } - - /** - * @notice Gets information about a hotfix. - * @param hash The abi encoded keccak256 hash of the hotfix transaction. - * @return Hotfix approved. - * @return Hotfix executed. - * @return Hotfix preparedEpoch. - */ - function getHotfixRecord(bytes32 hash) public view returns (bool, bool, uint256) { - return (hotfixes[hash].approved, hotfixes[hash].executed, hotfixes[hash].preparedEpoch); - } - - /** - * @notice Removes the proposals with the most upvotes from the queue, moving them to the - * approval stage. - * @dev If any of the top proposals have expired, they are deleted. - */ - function dequeueProposalsIfReady() public { - // solhint-disable-next-line not-rely-on-time - if (now >= lastDequeue.add(dequeueFrequency)) { - uint256 numProposalsToDequeue = Math.min(concurrentProposals, queue.list.numElements); - uint256[] memory dequeuedIds = queue.popN(numProposalsToDequeue); - - bool wasAnyProposalDequeued = false; - for (uint256 i = 0; i < numProposalsToDequeue; i = i.add(1)) { - uint256 proposalId = dequeuedIds[i]; - Proposals.Proposal storage proposal = proposals[proposalId]; - if (_isQueuedProposalExpired(proposal)) { - emit ProposalExpired(proposalId); - continue; - } - refundedDeposits[proposal.proposer] = refundedDeposits[proposal.proposer].add( - proposal.deposit - ); - // solhint-disable-next-line not-rely-on-time - proposal.timestamp = now; - if (emptyIndices.length != 0) { - uint256 indexOfLastEmptyIndex = emptyIndices.length.sub(1); - dequeued[emptyIndices[indexOfLastEmptyIndex]] = proposalId; - delete emptyIndices[indexOfLastEmptyIndex]; - emptyIndices.length = indexOfLastEmptyIndex; - } else { - dequeued.push(proposalId); - } - // solhint-disable-next-line not-rely-on-time - emit ProposalDequeued(proposalId, now); - wasAnyProposalDequeued = true; - } - if (wasAnyProposalDequeued) { - // solhint-disable-next-line not-rely-on-time - lastDequeue = now; - } - } - } - - /** - * @notice Returns whether or not a proposal is in the queue. - * @dev NOTE: proposal may be expired - * @param proposalId The ID of the proposal. - * @return Whether or not the proposal is in the queue. - */ - function isQueued(uint256 proposalId) public view returns (bool) { - return queue.contains(proposalId); - } - - /** - * @notice Returns whether or not a particular proposal is passing according to the constitution - * and the participation levels. - * @param proposalId The ID of the proposal. - * @return Whether or not the proposal is passing. - */ - function isProposalPassing(uint256 proposalId) external view returns (bool) { - return _isProposalPassing(proposals[proposalId]); - } - - /** - * @notice Returns whether or not a particular proposal is passing according to the constitution - * and the participation levels. - * @param proposal The proposal struct. - * @return Whether or not the proposal is passing. - */ - function _isProposalPassing(Proposals.Proposal storage proposal) private view returns (bool) { - FixidityLib.Fraction memory support = proposal.getSupportWithQuorumPadding( - participationParameters.baseline.multiply(participationParameters.baselineQuorumFactor) - ); - - if (proposal.transactions.length == 0) { - // default treshold - FixidityLib.Fraction memory threshold = _getConstitution(address(0), ""); - return support.gt(threshold); - } - - for (uint256 i = 0; i < proposal.transactions.length; i = i.add(1)) { - bytes4 functionId = ExtractFunctionSignature.extractFunctionSignature( - proposal.transactions[i].data - ); - FixidityLib.Fraction memory threshold = _getConstitution( - proposal.transactions[i].destination, - functionId - ); - if (support.lte(threshold)) { - return false; - } - } - return true; - } - - /** - * @notice Returns whether a proposal is dequeued at the given index. - * @param proposalId The ID of the proposal. - * @param index The index of the proposal ID in `dequeued`. - * @return Whether the proposal is in `dequeued`. - */ - function isDequeuedProposal(uint256 proposalId, uint256 index) external view returns (bool) { - return _isDequeuedProposal(proposals[proposalId], proposalId, index); - } - - /** - * @notice Returns whether a proposal is dequeued at the given index. - * @param proposal The proposal struct. - * @param proposalId The ID of the proposal. - * @param index The index of the proposal ID in `dequeued`. - * @return Whether the proposal is in `dequeued` at index. - */ - function _isDequeuedProposal( - Proposals.Proposal storage proposal, - uint256 proposalId, - uint256 index - ) private view returns (bool) { - require(index < dequeued.length, "Provided index greater than dequeue length."); - return proposal.exists() && dequeued[index] == proposalId; - } - - /** - * @notice Returns whether or not a dequeued proposal has expired. - * @param proposalId The ID of the proposal. - * @return Whether or not the dequeued proposal has expired. - */ - function isDequeuedProposalExpired(uint256 proposalId) external view returns (bool) { - Proposals.Proposal storage proposal = proposals[proposalId]; - return _isDequeuedProposalExpired(proposal, getProposalDequeuedStage(proposal)); - } - - /** - * @notice Returns whether or not a dequeued proposal has expired. - * @param proposal The proposal struct. - * @return Whether or not the dequeued proposal has expired. - */ - function _isDequeuedProposalExpired(Proposals.Proposal storage proposal, Proposals.Stage stage) - private - view - returns (bool) - { - // The proposal is considered expired under the following conditions: - // 1. Past the referendum stage and not passing. - // 2. Past the execution stage. - return ((stage > Proposals.Stage.Execution) || - (stage > Proposals.Stage.Referendum && !_isProposalPassing(proposal))); - } - - /** - * @notice Returns whether or not a queued proposal has expired. - * @param proposalId The ID of the proposal. - * @return Whether or not the dequeued proposal has expired. - */ - function isQueuedProposalExpired(uint256 proposalId) public view returns (bool) { - return _isQueuedProposalExpired(proposals[proposalId]); - } - - /** - * @notice Returns whether or not a queued proposal has expired. - * @param proposal The proposal struct. - * @return Whether or not the dequeued proposal has expired. - */ - function _isQueuedProposalExpired(Proposals.Proposal storage proposal) - private - view - returns (bool) - { - // solhint-disable-next-line not-rely-on-time - return now >= proposal.timestamp.add(queueExpiry); - } - - /** - * @notice Deletes a dequeued proposal. - * @param proposal The proposal struct. - * @param proposalId The ID of the proposal to delete. - * @param index The index of the proposal ID in `dequeued`. - * @dev Must always be preceded by `isDequeuedProposal`, which checks `index`. - */ - function deleteDequeuedProposal( - Proposals.Proposal storage proposal, - uint256 proposalId, - uint256 index - ) private { - if (proposal.isApproved() && proposal.networkWeight != 0) { - updateParticipationBaseline(proposal); - } - dequeued[index] = 0; - emptyIndices.push(index); - delete proposals[proposalId]; - } - - /** - * @notice Updates the participation baseline based on the proportion of BondedDeposit weight - * that participated in the proposal's Referendum stage. - * @param proposal The proposal struct. - */ - function updateParticipationBaseline(Proposals.Proposal storage proposal) private { - FixidityLib.Fraction memory participation = proposal.getParticipation(); - FixidityLib.Fraction memory participationComponent = participation.multiply( - participationParameters.baselineUpdateFactor - ); - FixidityLib.Fraction memory baselineComponent = participationParameters.baseline.multiply( - FixidityLib.fixed1().subtract(participationParameters.baselineUpdateFactor) - ); - participationParameters.baseline = participationComponent.add(baselineComponent); - if (participationParameters.baseline.lt(participationParameters.baselineFloor)) { - participationParameters.baseline = participationParameters.baselineFloor; - } - emit ParticipationBaselineUpdated(participationParameters.baseline.unwrap()); - } - - /** - * @notice Returns the constitution for a particular destination and function ID. - * @param destination The destination address to get the constitution for. - * @param functionId The function ID to get the constitution for, zero for the destination - * default. - * @return The ratio of yes:no votes needed to exceed in order to pass the proposal. - */ - function getConstitution(address destination, bytes4 functionId) external view returns (uint256) { - return _getConstitution(destination, functionId).unwrap(); - } - - function _getConstitution(address destination, bytes4 functionId) - internal - view - returns (FixidityLib.Fraction memory) - { - // Default to a simple majority. - FixidityLib.Fraction memory threshold = FixidityLib.wrap(FIXED_HALF); - if (constitution[destination].functionThresholds[functionId].unwrap() != 0) { - threshold = constitution[destination].functionThresholds[functionId]; - } else if (constitution[destination].defaultThreshold.unwrap() != 0) { - threshold = constitution[destination].defaultThreshold; - } - return threshold; - } - - /** - * @notice Returns max number of votes cast by an account. - * @param account The address of the account. - * @return The total number of votes cast by an account. - */ - function getAmountOfGoldUsedForVoting(address account) public view returns (uint256) { - Voter storage voter = voters[account]; - - uint256 upvotedProposalId = voter.upvote.proposalId; - bool isVotingQueue = upvotedProposalId != 0 && - isQueued(upvotedProposalId) && - !isQueuedProposalExpired(upvotedProposalId); - - if (isVotingQueue) { - uint256 weight = getLockedGold().getAccountTotalLockedGold(account); - return weight; - } - - uint256 maxUsed = 0; - for (uint256 index = 0; index < dequeued.length; index = index.add(1)) { - Proposals.Proposal storage proposal = proposals[dequeued[index]]; - bool isVotingReferendum = (getProposalDequeuedStage(proposal) == Proposals.Stage.Referendum); - - if (!isVotingReferendum) { - continue; - } - - VoteRecord storage voteRecord = voter.referendumVotes[index]; - uint256 votesCast = voteRecord.yesVotes.add(voteRecord.noVotes).add(voteRecord.abstainVotes); - maxUsed = Math.max( - maxUsed, - // backward compatibility for transition period - this should be updated later on - votesCast == 0 ? voteRecord.deprecated_weight : votesCast - ); - } - return maxUsed; - } - - /** - * @notice When delegator removes votes from delegatee during the time when delegator is voting - * for governance proposal, this method will remove votes from voted proposal proportionally. - * @param account The address of the account. - * @param newVotingPower The adjusted voting power of delegatee. - */ - function removeVotesWhenRevokingDelegatedVotes(address account, uint256 newVotingPower) - public - onlyLockedGold - { - _removeVotesWhenRevokingDelegatedVotes(account, newVotingPower); - } - - /** - * @notice When delegator removes votes from delegatee during the time when delegator is voting - * for governance proposal, this method will remove votes from voted proposal proportionally. - * @param account The address of the account. - * @param newVotingPower The adjusted voting power of delegatee. - */ - function _removeVotesWhenRevokingDelegatedVotes(address account, uint256 newVotingPower) - internal - { - Voter storage voter = voters[account]; - - for (uint256 index = 0; index < dequeued.length; index = index.add(1)) { - Proposals.Proposal storage proposal = proposals[dequeued[index]]; - bool isVotingReferendum = (getProposalDequeuedStage(proposal) == Proposals.Stage.Referendum); - - if (!isVotingReferendum) { - continue; - } - - VoteRecord storage voteRecord = voter.referendumVotes[index]; - uint256 sumOfVotes = voteRecord.yesVotes.add(voteRecord.noVotes).add(voteRecord.abstainVotes); - - if (sumOfVotes > newVotingPower) { - uint256 toRemove = sumOfVotes.sub(newVotingPower); - - uint256 abstainToRemove = getVotesPortion(toRemove, voteRecord.abstainVotes, sumOfVotes); - uint256 yesToRemove = getVotesPortion(toRemove, voteRecord.yesVotes, sumOfVotes); - uint256 noToRemove = getVotesPortion(toRemove, voteRecord.noVotes, sumOfVotes); - - uint256 totalRemoved = abstainToRemove.add(yesToRemove).add(noToRemove); - - uint256 yesVotes = voteRecord.yesVotes.sub(yesToRemove); - uint256 noVotes = voteRecord.noVotes.sub(noToRemove); - uint256 abstainVotes = voteRecord.abstainVotes.sub(abstainToRemove); - - if (totalRemoved < toRemove) { - // in case of rounding error - uint256 roundingToRemove = toRemove.sub(totalRemoved); - - uint256 toRemoveRounding = Math.min(roundingToRemove, yesVotes); - yesVotes = yesVotes.sub(toRemoveRounding); - roundingToRemove = roundingToRemove.sub(toRemoveRounding); - - if (roundingToRemove != 0) { - toRemoveRounding = Math.min(roundingToRemove, noVotes); - noVotes = noVotes.sub(toRemoveRounding); - roundingToRemove = roundingToRemove.sub(toRemoveRounding); - } - - if (roundingToRemove != 0) { - toRemoveRounding = Math.min(roundingToRemove, abstainVotes); - abstainVotes = abstainVotes.sub(toRemoveRounding); - } - } - - proposal.updateVote( - voteRecord.yesVotes, - voteRecord.noVotes, - voteRecord.abstainVotes, - yesVotes, - noVotes, - abstainVotes - ); - - voteRecord.abstainVotes = abstainVotes; - voteRecord.yesVotes = yesVotes; - voteRecord.noVotes = noVotes; - } - } - } - - /** - * Returns amount of votes that should be removed from delegatee's proposal voting. - * @param totalToRemove Total votes to be removed. - * @param votes Yes/no/abstrain votes - * @param sumOfAllVotes Sum of yes, no, and abstain votes. - */ - function getVotesPortion(uint256 totalToRemove, uint256 votes, uint256 sumOfAllVotes) - private - pure - returns (uint256) - { - return - FixidityLib - .newFixed(totalToRemove) - .multiply(FixidityLib.newFixedFraction(votes, sumOfAllVotes)) - .fromFixed(); - } - - /** - * @notice Returns the stage of a dequeued proposal. - * @param proposal The proposal struct. - * @return The stage of the dequeued proposal. - * @dev Must be called on a dequeued proposal. - */ - function getProposalDequeuedStage(Proposals.Proposal storage proposal) - internal - view - returns (Proposals.Stage) - { - uint256 stageStartTime = proposal.timestamp.add(stageDurations.referendum).add( - stageDurations.execution - ); - // solhint-disable-next-line not-rely-on-time - if ( - now >= stageStartTime && - (proposal.transactions.length != 0 || - // proposals with 0 transactions can expire only when not approved or not passing - !proposal.isApproved() || - !_isProposalPassing(proposal)) - ) { - return Proposals.Stage.Expiration; - } - stageStartTime = stageStartTime.sub(stageDurations.execution); - // solhint-disable-next-line not-rely-on-time - if (now >= stageStartTime) { - return Proposals.Stage.Execution; - } - return Proposals.Stage.Referendum; - } -} diff --git a/packages/protocol/contracts/governance/GovernanceApproverMultiSig.sol b/packages/protocol/contracts/governance/GovernanceApproverMultiSig.sol deleted file mode 100644 index 0e12dafda..000000000 --- a/packages/protocol/contracts/governance/GovernanceApproverMultiSig.sol +++ /dev/null @@ -1,12 +0,0 @@ -pragma solidity ^0.5.13; - -import "../common/MultiSig.sol"; - -/* solhint-disable no-empty-blocks */ -contract GovernanceApproverMultiSig is MultiSig { - /** - * @notice Sets initialized == true on implementation contracts - * @param test Set to true to skip implementation initialization - */ - constructor(bool test) public MultiSig(test) {} -} diff --git a/packages/protocol/contracts/governance/GovernanceSlasher.sol b/packages/protocol/contracts/governance/GovernanceSlasher.sol deleted file mode 100644 index 5f6264d70..000000000 --- a/packages/protocol/contracts/governance/GovernanceSlasher.sol +++ /dev/null @@ -1,81 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; - -import "../common/Initializable.sol"; -import "../common/UsingRegistry.sol"; - -contract GovernanceSlasher is Ownable, Initializable, UsingRegistry { - using SafeMath for uint256; - // Maps a slashed address to the amount to be slashed. - // Note that there is no reward paid when slashing via governance. - mapping(address => uint256) slashed; - - event SlashingApproved(address indexed account, uint256 amount); - event GovernanceSlashPerformed(address indexed account, uint256 amount); - - /** - * @notice Sets initialized == true on implementation contracts - * @param test Set to true to skip implementation initialization - */ - constructor(bool test) public Initializable(test) {} - - /** - * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. - * @param registryAddress The address of the registry core smart contract. - */ - function initialize(address registryAddress) external initializer { - _transferOwnership(msg.sender); - setRegistry(registryAddress); - } - - /** - * @notice Sets account penalty. - * @param account Address that is punished. - * @param penalty Amount of penalty in wei. - * @dev Only callable by governance. - */ - function approveSlashing(address account, uint256 penalty) external onlyOwner { - slashed[account] = slashed[account].add(penalty); - emit SlashingApproved(account, penalty); - } - - /** - * @notice Gets account penalty. - * @param account Address that is punished. - * @return Amount slashed. - */ - function getApprovedSlashing(address account) external view returns (uint256) { - return slashed[account]; - } - - /** - * @notice Calls `LockedGold.slash` on `account` if `account` has an entry in `slashed`. - * @param account Account to slash - * @param electionLessers Lesser pointers for slashing locked election gold. - * @param electionGreaters Greater pointers for slashing locked election gold. - * @param electionIndices Indices of groups voted by slashed account. - */ - function slash( - address account, - address[] calldata electionLessers, - address[] calldata electionGreaters, - uint256[] calldata electionIndices - ) external returns (bool) { - uint256 penalty = slashed[account]; - require(penalty > 0, "No penalty given by governance"); - slashed[account] = 0; - getLockedGold().slash( - account, - penalty, - address(0), - 0, - electionLessers, - electionGreaters, - electionIndices - ); - emit GovernanceSlashPerformed(account, penalty); - return true; - } -} diff --git a/packages/protocol/contracts/governance/LockedGold.sol b/packages/protocol/contracts/governance/LockedGold.sol deleted file mode 100755 index e85f0cd3d..000000000 --- a/packages/protocol/contracts/governance/LockedGold.sol +++ /dev/null @@ -1,896 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/Math.sol"; -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; -import "openzeppelin-solidity/contracts/utils/Address.sol"; -import "openzeppelin-solidity/contracts/utils/EnumerableSet.sol"; - -import "./interfaces/ILockedGold.sol"; - -import "../common/FixidityLib.sol"; -import "../common/Initializable.sol"; -import "../common/Signatures.sol"; -import "../common/UsingRegistry.sol"; -import "../common/interfaces/ICeloVersionedContract.sol"; -import "../common/libraries/ReentrancyGuard.sol"; - -contract LockedGold is - ILockedGold, - ICeloVersionedContract, - ReentrancyGuard, - Initializable, - UsingRegistry -{ - using SafeMath for uint256; - using Address for address payable; // prettier-ignore - using FixidityLib for FixidityLib.Fraction; - using EnumerableSet for EnumerableSet.AddressSet; - - struct PendingWithdrawal { - // The value of the pending withdrawal. - uint256 value; - // The timestamp at which the pending withdrawal becomes available. - uint256 timestamp; - } - - // NOTE: This contract does not store an account's locked gold that is being used in electing - // validators. - struct Balances { - // The amount of locked gold that this account has that is not currently participating in - // validator elections. - uint256 nonvoting; - // Gold that has been unlocked and will become available for withdrawal. - PendingWithdrawal[] pendingWithdrawals; - } - - struct DelegatedInfo { - FixidityLib.Fraction percentage; - uint256 currentAmount; - } - - struct Delegated { - EnumerableSet.AddressSet delegatees; - // delegatees with how much percent delegatees are getting - // Celo at the time of delegation/latest update - mapping(address => DelegatedInfo) delegateesWithPercentagesAndAmount; - FixidityLib.Fraction totalDelegatedCeloFraction; - } - - mapping(address => Balances) internal balances; - - // Iterable map to store whitelisted identifiers. - // Necessary to allow iterating over whitelisted IDs to check ID's address at runtime. - mapping(bytes32 => bool) internal slashingMap; - bytes32[] public slashingWhitelist; - - modifier onlySlasher { - require( - registry.isOneOf(slashingWhitelist, msg.sender), - "Caller is not a whitelisted slasher." - ); - _; - } - - function isSlasher(address slasher) external view returns (bool) { - return (registry.isOneOf(slashingWhitelist, slasher)); - } - - uint256 public totalNonvoting; - uint256 public unlockingPeriod; - - // Info about delegator - mapping(address => Delegated) delegatorInfo; - // Celo that was delegated to this particular address - mapping(address => uint256) public totalDelegatedCelo; - - // maximum amount of allowed delegatees - uint256 maxDelegateesCount; - - event UnlockingPeriodSet(uint256 period); - event GoldLocked(address indexed account, uint256 value); - event GoldUnlocked(address indexed account, uint256 value, uint256 available); - event GoldRelocked(address indexed account, uint256 value); - event GoldWithdrawn(address indexed account, uint256 value); - event SlasherWhitelistAdded(string indexed slasherIdentifier); - event SlasherWhitelistRemoved(string indexed slasherIdentifier); - event AccountSlashed( - address indexed slashed, - uint256 penalty, - address indexed reporter, - uint256 reward - ); - event CeloDelegated( - address indexed delegator, - address indexed delegatee, - uint256 percent, - uint256 amount - ); - event DelegatedCeloRevoked( - address indexed delegator, - address indexed delegatee, - uint256 percent, - uint256 amount - ); - event MaxDelegateesCountSet(uint256 value); - - /** - * @notice Returns the storage, major, minor, and patch version of the contract. - * @return Storage version of the contract. - * @return Major version of the contract. - * @return Minor version of the contract. - * @return Patch version of the contract. - */ - function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { - return (1, 1, 4, 0); - } - - /** - * @notice Sets initialized == true on implementation contracts - * @param test Set to true to skip implementation initialization - */ - constructor(bool test) public Initializable(test) {} - - /** - * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. - * @param registryAddress The address of the registry core smart contract. - * @param _unlockingPeriod The unlocking period in seconds. - */ - function initialize(address registryAddress, uint256 _unlockingPeriod) external initializer { - _transferOwnership(msg.sender); - setRegistry(registryAddress); - setUnlockingPeriod(_unlockingPeriod); - maxDelegateesCount = 10; - } - - /** - * @notice Sets the duration in seconds users must wait before withdrawing gold after unlocking. - * @param value The unlocking period in seconds. - */ - function setUnlockingPeriod(uint256 value) public onlyOwner { - require(value != unlockingPeriod, "Unlocking period not changed"); - unlockingPeriod = value; - emit UnlockingPeriodSet(value); - } - - /** - * @notice Sets max delegatees count. - * @param value The max delegatees count. - */ - function setMaxDelegateesCount(uint256 value) public onlyOwner { - maxDelegateesCount = value; - emit MaxDelegateesCountSet(value); - } - - /** - * @notice Locks gold to be used for voting. - */ - function lock() external payable nonReentrant { - require( - getAccounts().isAccount(msg.sender), - "Must first register address with Account.createAccount" - ); - _incrementNonvotingAccountBalance(msg.sender, msg.value); - _updateDelegatedAmount(msg.sender); - emit GoldLocked(msg.sender, msg.value); - } - - /** - * @notice Increments the non-voting balance for an account. - * @param account The account whose non-voting balance should be incremented. - * @param value The amount by which to increment. - * @dev Can only be called by the registered Election smart contract. - */ - function incrementNonvotingAccountBalance(address account, uint256 value) - external - onlyRegisteredContract(ELECTION_REGISTRY_ID) - { - _incrementNonvotingAccountBalance(account, value); - } - - /** - * @notice Decrements the non-voting balance for an account. - * @param account The account whose non-voting balance should be decremented. - * @param value The amount by which to decrement. - * @dev Can only be called by the registered "Election" smart contract. - */ - function decrementNonvotingAccountBalance(address account, uint256 value) - external - onlyRegisteredContract(ELECTION_REGISTRY_ID) - { - _decrementNonvotingAccountBalance(account, value); - } - - /** - * @notice Increments the non-voting balance for an account. - * @param account The account whose non-voting balance should be incremented. - * @param value The amount by which to increment. - */ - function _incrementNonvotingAccountBalance(address account, uint256 value) private { - balances[account].nonvoting = balances[account].nonvoting.add(value); - totalNonvoting = totalNonvoting.add(value); - } - - /** - * @notice Decrements the non-voting balance for an account. - * @param account The account whose non-voting balance should be decremented. - * @param value The amount by which to decrement. - */ - function _decrementNonvotingAccountBalance(address account, uint256 value) private { - balances[account].nonvoting = balances[account].nonvoting.sub(value); - totalNonvoting = totalNonvoting.sub(value); - } - - /** - * @notice Unlocks gold that becomes withdrawable after the unlocking period. - * @param value The amount of gold to unlock. - */ - function unlock(uint256 value) external nonReentrant { - require( - getAccounts().isAccount(msg.sender), - "Sender must be registered with Account.createAccount to lock or unlock" - ); - Balances storage account = balances[msg.sender]; - - uint256 totalLockedGold = getAccountTotalLockedGold(msg.sender); - // Prevent unlocking gold when voting on governance proposals so that the gold cannot be - // used to vote more than once. - uint256 remainingLockedGold = totalLockedGold.sub(value); - - uint256 totalReferendumVotes = getGovernance().getAmountOfGoldUsedForVoting(msg.sender); - require( - remainingLockedGold >= totalReferendumVotes, - "Not enough unlockable celo. Celo is locked in voting." - ); - - FixidityLib.Fraction memory delegatedPercentage = delegatorInfo[msg.sender] - .totalDelegatedCeloFraction; - - if (FixidityLib.gt(delegatedPercentage, FixidityLib.newFixed(0))) { - revokeFromDelegatedWhenUnlocking(msg.sender, value); - } - - uint256 balanceRequirement = getValidators().getAccountLockedGoldRequirement(msg.sender); - require( - balanceRequirement == 0 || balanceRequirement <= remainingLockedGold, - "Either account doesn't have enough locked Celo or locked Celo is being used for voting." - ); - _decrementNonvotingAccountBalance(msg.sender, value); - uint256 available = now.add(unlockingPeriod); - // CERTORA: the slot containing the length could be MAX_UINT - account.pendingWithdrawals.push(PendingWithdrawal(value, available)); - emit GoldUnlocked(msg.sender, value, available); - } - - /** - * @notice Relocks gold that has been unlocked but not withdrawn. - * @param index The index of the pending withdrawal to relock from. - * @param value The value to relock from the specified pending withdrawal. - */ - function relock(uint256 index, uint256 value) external nonReentrant { - require( - getAccounts().isAccount(msg.sender), - "Sender must be registered with Account.createAccount to lock or relock" - ); - Balances storage account = balances[msg.sender]; - require(index < account.pendingWithdrawals.length, "Bad pending withdrawal index"); - PendingWithdrawal storage pendingWithdrawal = account.pendingWithdrawals[index]; - require(value <= pendingWithdrawal.value, "Requested value larger than pending value"); - if (value == pendingWithdrawal.value) { - deletePendingWithdrawal(account.pendingWithdrawals, index); - } else { - pendingWithdrawal.value = pendingWithdrawal.value.sub(value); - } - _incrementNonvotingAccountBalance(msg.sender, value); - _updateDelegatedAmount(msg.sender); - emit GoldRelocked(msg.sender, value); - } - - /** - * @notice Withdraws gold that has been unlocked after the unlocking period has passed. - * @param index The index of the pending withdrawal to withdraw. - */ - function withdraw(uint256 index) external nonReentrant { - require( - getAccounts().isAccount(msg.sender), - "Sender must be registered with Account.createAccount to withdraw" - ); - Balances storage account = balances[msg.sender]; - require(index < account.pendingWithdrawals.length, "Bad pending withdrawal index"); - PendingWithdrawal storage pendingWithdrawal = account.pendingWithdrawals[index]; - require(now >= pendingWithdrawal.timestamp, "Pending withdrawal not available"); - uint256 value = pendingWithdrawal.value; - deletePendingWithdrawal(account.pendingWithdrawals, index); - require(value <= address(this).balance, "Inconsistent balance"); - msg.sender.sendValue(value); - emit GoldWithdrawn(msg.sender, value); - } - - /** - * @notice Returns the total amount of locked gold in the system. Note that this does not include - * gold that has been unlocked but not yet withdrawn. - * @return The total amount of locked gold in the system. - */ - function getTotalLockedGold() external view returns (uint256) { - return totalNonvoting.add(getElection().getTotalVotes()); - } - - /** - * @notice Returns the total amount of locked gold not being used to vote in elections. - * @return The total amount of locked gold not being used to vote in elections. - */ - function getNonvotingLockedGold() external view returns (uint256) { - return totalNonvoting; - } - - /** - * Delegates CELO to delegatee. - * @param delegatee The delegatee account. - * @param delegateFraction Fraction of total CELO that will be delegated from delegatee. Fixidity fraction - */ - function delegateGovernanceVotes(address delegatee, uint256 delegateFraction) external { - FixidityLib.Fraction memory percentageToDelegate = FixidityLib.wrap(delegateFraction); - require( - FixidityLib.lte(percentageToDelegate, FixidityLib.fixed1()), - "Delegate fraction must be less than or equal to 1" - ); - address delegatorAccount = getAccounts().voteSignerToAccount(msg.sender); - address delegateeAccount = getAccounts().voteSignerToAccount(delegatee); - - IValidators validators = getValidators(); - require(!validators.isValidator(delegatorAccount), "Validators cannot delegate votes."); - require( - !validators.isValidatorGroup(delegatorAccount), - "Validator groups cannot delegate votes." - ); - - Delegated storage delegated = delegatorInfo[delegatorAccount]; - delegated.delegatees.add(delegateeAccount); - require(delegated.delegatees.length() <= maxDelegateesCount, "Too many delegatees"); - - DelegatedInfo storage currentDelegateeInfo = delegated - .delegateesWithPercentagesAndAmount[delegateeAccount]; - - require( - FixidityLib.gte(percentageToDelegate, currentDelegateeInfo.percentage), - "Cannot decrease delegated amount - use revokeDelegatedGovernanceVotes." - ); - - FixidityLib.Fraction memory requestedToDelegate = delegated - .totalDelegatedCeloFraction - .subtract(currentDelegateeInfo.percentage) - .add(percentageToDelegate); - - require( - FixidityLib.lte(requestedToDelegate, FixidityLib.fixed1()), - "Cannot delegate more than 100%" - ); - - uint256 totalLockedGold = getAccountTotalLockedGold(delegatorAccount); - if (totalLockedGold == 0) { - delegated.totalDelegatedCeloFraction = delegated - .totalDelegatedCeloFraction - .subtract(currentDelegateeInfo.percentage) - .add(percentageToDelegate); - currentDelegateeInfo.percentage = percentageToDelegate; - - emit CeloDelegated( - delegatorAccount, - delegateeAccount, - FixidityLib.unwrap(percentageToDelegate), - currentDelegateeInfo.currentAmount - ); - return; - } - - uint256 totalReferendumVotes = getGovernance().getAmountOfGoldUsedForVoting(delegatorAccount); - - if (totalReferendumVotes != 0) { - FixidityLib.Fraction memory referendumVotesInPercents = FixidityLib.newFixedFraction( - totalReferendumVotes, - totalLockedGold - ); - require( - FixidityLib.lte(referendumVotesInPercents.add(requestedToDelegate), FixidityLib.fixed1()), - "Cannot delegate votes that are voting in referendum" - ); - } - - // amount that will really be delegated - whatever is already - // delegated to this particular delagatee is already subracted from this - uint256 amountToDelegate = FixidityLib - .newFixed(totalLockedGold) - .multiply(percentageToDelegate) - .subtract(FixidityLib.newFixed(currentDelegateeInfo.currentAmount)) - .fromFixed(); - - delegated.totalDelegatedCeloFraction = delegated - .totalDelegatedCeloFraction - .subtract(currentDelegateeInfo.percentage) - .add(percentageToDelegate); - currentDelegateeInfo.percentage = percentageToDelegate; - - currentDelegateeInfo.currentAmount = currentDelegateeInfo.currentAmount.add(amountToDelegate); - totalDelegatedCelo[delegateeAccount] = totalDelegatedCelo[delegateeAccount].add( - amountToDelegate - ); - - emit CeloDelegated( - delegatorAccount, - delegateeAccount, - FixidityLib.unwrap(percentageToDelegate), - currentDelegateeInfo.currentAmount - ); - } - - /** - * Revokes delegated CELO. - * @param delegatee The delegatee acount. - * @param revokeFraction Fraction of total CELO that will be revoked from delegatee. Fixidity fraction - */ - function revokeDelegatedGovernanceVotes(address delegatee, uint256 revokeFraction) external { - FixidityLib.Fraction memory percentageToRevoke = FixidityLib.wrap(revokeFraction); - - require( - FixidityLib.lte(percentageToRevoke, FixidityLib.fixed1()), - "Revoke fraction must be less than or equal to 1" - ); - - address delegatorAccount = getAccounts().voteSignerToAccount(msg.sender); - Delegated storage delegated = delegatorInfo[delegatorAccount]; - require( - FixidityLib.gte(delegated.totalDelegatedCeloFraction, percentageToRevoke), - "Not enough total delegated percents" - ); - - address delegateeAccount = getAccounts().voteSignerToAccount(delegatee); - _updateDelegatedAmount(delegatorAccount, delegateeAccount); - - DelegatedInfo storage currentDelegateeInfo = delegated - .delegateesWithPercentagesAndAmount[delegateeAccount]; - - require( - FixidityLib.gte(currentDelegateeInfo.percentage, percentageToRevoke), - "Not enough delegated percents" - ); - - currentDelegateeInfo.percentage = currentDelegateeInfo.percentage.subtract(percentageToRevoke); - - uint256 totalLockedGold = getAccountTotalLockedGold(delegatorAccount); - - uint256 amountToRevoke = FixidityLib.unwrap(currentDelegateeInfo.percentage) == 0 - ? currentDelegateeInfo.currentAmount - : Math.min( - FixidityLib.newFixed(totalLockedGold).multiply(percentageToRevoke).fromFixed(), - currentDelegateeInfo.currentAmount - ); - - _decreaseDelegateeVotingPower(delegateeAccount, amountToRevoke, currentDelegateeInfo); - - delegated.totalDelegatedCeloFraction = delegated.totalDelegatedCeloFraction.subtract( - percentageToRevoke - ); - - if (FixidityLib.unwrap(currentDelegateeInfo.percentage) == 0) { - delegated.delegatees.remove(delegateeAccount); - } - - emit DelegatedCeloRevoked( - delegatorAccount, - delegateeAccount, - FixidityLib.unwrap(percentageToRevoke), - amountToRevoke - ); - } - - /** - * Revokes amount during unlocking. It will revoke votes from voted proposals if necessary. - * @param delegator The delegator account. - * @param amountToRevoke The amount to revoke. - */ - function revokeFromDelegatedWhenUnlocking(address delegator, uint256 amountToRevoke) private { - address[] memory delegatees = getDelegateesOfDelegator(delegator); - - Delegated storage delegated = delegatorInfo[delegator]; - - for (uint256 i = 0; i < delegatees.length; i = i.add(1)) { - DelegatedInfo storage currentDelegateeInfo = delegated - .delegateesWithPercentagesAndAmount[delegatees[i]]; - (uint256 expected, uint256 real) = _getDelegatorDelegateeExpectedAndRealAmount( - delegator, - delegatees[i] - ); - uint256 delegateeAmountToRevoke = FixidityLib - .newFixed(amountToRevoke) - .multiply(currentDelegateeInfo.percentage) - .fromFixed(); - delegateeAmountToRevoke = delegateeAmountToRevoke.sub(expected.sub(real)); - _decreaseDelegateeVotingPower(delegatees[i], delegateeAmountToRevoke, currentDelegateeInfo); - emit DelegatedCeloRevoked(delegator, delegatees[i], 0, delegateeAmountToRevoke); - } - } - - /** - * Decreases delegatee voting power when removing or unlocking delegated votes. - * @param delegatee The delegatee. - * @param amountToRevoke Amount to revoke. - * @param delegateeInfo Delegatee info. - */ - function _decreaseDelegateeVotingPower( - address delegatee, - uint256 amountToRevoke, - DelegatedInfo storage delegateeInfo - ) private { - uint256 delegateeTotalVotingPower = getAccountTotalGovernanceVotingPower(delegatee); - uint256 totalReferendumVotes = getGovernance().getAmountOfGoldUsedForVoting(delegatee); - uint256 unusedReferendumVotes = delegateeTotalVotingPower.sub(totalReferendumVotes); - if (unusedReferendumVotes < amountToRevoke) { - getGovernance().removeVotesWhenRevokingDelegatedVotes( - delegatee, - delegateeTotalVotingPower.sub(amountToRevoke) - ); - } - delegateeInfo.currentAmount = delegateeInfo.currentAmount.sub(amountToRevoke); - totalDelegatedCelo[delegatee] = totalDelegatedCelo[delegatee].sub(amountToRevoke); - } - - /** - * Updates real delegated amount to all delegator's delegatees. - * There might be discrepancy because of validator rewards or extra locked gold. - * @param delegator The delegator address. - */ - function updateDelegatedAmount(address delegator) public { - address delegatorAccount = getAccounts().voteSignerToAccount(delegator); - _updateDelegatedAmount(delegatorAccount); - } - - function _updateDelegatedAmount(address delegator) private { - address delegatorAccount = getAccounts().voteSignerToAccount(delegator); - EnumerableSet.AddressSet storage delegatees = delegatorInfo[delegatorAccount].delegatees; - for (uint256 i = 0; i < delegatees.length(); i = i.add(1)) { - _updateDelegatedAmount(delegatorAccount, delegatees.get(i)); - } - } - - /** - * Updates real delegated amount to delegatee. - * There might be discrepancy because of validator rewards or extra locked gold. - * Voting power will always be smaller or equal to what it is supposed to be. - * @param delegator The delegator address. - * @param delegatee The delegatee address. - */ - function updateDelegatedAmount(address delegator, address delegatee) public returns (uint256) { - address delegatorAccount = getAccounts().voteSignerToAccount(delegator); - address delegateeAccount = getAccounts().voteSignerToAccount(delegatee); - - return _updateDelegatedAmount(delegatorAccount, delegateeAccount); - } - - /** - * Updates real delegated amount to delegatee. - * There might be discrepancy because of validator rewards or extra locked gold. - * Voting power will always be smaller or equal to what it is supposed to be. - * @param delegator The delegator address. - * @param delegatee The delegatee address. - */ - function _updateDelegatedAmount(address delegator, address delegatee) internal returns (uint256) { - Delegated storage delegated = delegatorInfo[delegator]; - require( - FixidityLib.unwrap(delegated.totalDelegatedCeloFraction) != 0, - "delegator is not delegating" - ); - DelegatedInfo storage currentDelegateeInfo = delegated - .delegateesWithPercentagesAndAmount[delegatee]; - require( - FixidityLib.unwrap(currentDelegateeInfo.percentage) != 0, - "delegator is not delegating for delegatee" - ); - - (uint256 expected, uint256 real) = getDelegatorDelegateeExpectedAndRealAmount( - delegator, - delegatee - ); - - currentDelegateeInfo.currentAmount = expected; - totalDelegatedCelo[delegatee] = totalDelegatedCelo[delegatee].sub(real).add(expected); - - return expected; - } - - /** - * Returns how many percents of CELO is account delegating. - * @param account The account address. - */ - function getAccountTotalDelegatedFraction(address account) public view returns (uint256) { - Delegated storage delegated = delegatorInfo[account]; - return FixidityLib.unwrap(delegated.totalDelegatedCeloFraction); - } - - /** - * @notice Returns the total amount of locked gold for an account. - * @param account The account. - * @return The total amount of locked gold for an account. - */ - function getAccountTotalLockedGold(address account) public view returns (uint256) { - uint256 total = balances[account].nonvoting; - return total.add(getElection().getTotalVotesByAccount(account)); - } - - /** - * @notice Returns the total amount of locked gold + delegated gold for an account. - * @param account The account. - * @return The total amount of locked gold + delegated gold for an account. - */ - function getAccountTotalGovernanceVotingPower(address account) public view returns (uint256) { - FixidityLib.Fraction memory availableUndelegatedPercents = FixidityLib.fixed1().subtract( - FixidityLib.wrap(getAccountTotalDelegatedFraction(account)) - ); - uint256 totalLockedGold = getAccountTotalLockedGold(account); - - uint256 availableForVoting = FixidityLib - .newFixed(totalLockedGold) - .multiply(availableUndelegatedPercents) - .fromFixed(); - - return availableForVoting.add(totalDelegatedCelo[account]); - } - - /** - * Return percentage and amount that delegator assigned to delegateee. - * Please note that amount doesn't have to be up to date. - * In such case please use `updateDelegatedBalance`. - * @param delegator The delegator address. - * @param delegatee The delegatee address. - * @return fraction The fraction that is delegator asigning to delegatee. - * @return currentAmount The current actual Celo amount that is assigned to delegatee. - */ - function getDelegatorDelegateeInfo(address delegator, address delegatee) - external - view - returns (uint256 fraction, uint256 currentAmount) - { - DelegatedInfo storage currentDelegateeInfo = delegatorInfo[delegator] - .delegateesWithPercentagesAndAmount[delegatee]; - - fraction = FixidityLib.unwrap(currentDelegateeInfo.percentage); - currentAmount = currentDelegateeInfo.currentAmount; - } - - /** - * Returns expected vs real delegated amount. - * If there is a discrepancy it can be fixed by calling `updateDelegatedAmount` function. - * @param delegator The delegator address. - * @param delegatee The delegatee address. - * @return expected The expected amount. - * @return real The real amount. - */ - function getDelegatorDelegateeExpectedAndRealAmount(address delegator, address delegatee) - public - view - returns (uint256 expected, uint256 real) - { - address delegatorAccount = getAccounts().voteSignerToAccount(delegator); - address delegateeAccount = getAccounts().voteSignerToAccount(delegatee); - - (expected, real) = _getDelegatorDelegateeExpectedAndRealAmount( - delegatorAccount, - delegateeAccount - ); - } - - /** - * Returns expected vs real delegated amount. - * If there is a discrepancy it can be fixed by calling `updateDelegatedAmount` function. - * @param delegator The delegator address. - * @param delegatee The delegatee address. - * @return expected The expected amount. - * @return real The real amount. - */ - function _getDelegatorDelegateeExpectedAndRealAmount(address delegator, address delegatee) - private - view - returns (uint256 expected, uint256 real) - { - DelegatedInfo storage currentDelegateeInfo = delegatorInfo[delegator] - .delegateesWithPercentagesAndAmount[delegatee]; - - uint256 amountToDelegate = FixidityLib - .newFixed(getAccountTotalLockedGold(delegator)) - .multiply(currentDelegateeInfo.percentage) - .fromFixed(); - - expected = amountToDelegate; - real = currentDelegateeInfo.currentAmount; - } - - /** - * Retuns all delegatees of delegator - * @param delegator The delegator address. - */ - function getDelegateesOfDelegator(address delegator) public view returns (address[] memory) { - address[] memory values = delegatorInfo[delegator].delegatees.enumerate(); - return values; - } - - /** - * @notice Returns the total amount of non-voting locked gold for an account. - * @param account The account. - * @return The total amount of non-voting locked gold for an account. - */ - function getAccountNonvotingLockedGold(address account) external view returns (uint256) { - return balances[account].nonvoting; - } - - /** - * @notice Returns the pending withdrawals from unlocked gold for an account. - * @param account The address of the account. - * @return The value for each pending withdrawal. - * @return The timestamp for each pending withdrawal. - */ - function getPendingWithdrawals(address account) - external - view - returns (uint256[] memory, uint256[] memory) - { - require( - getAccounts().isAccount(account), - "Unknown account: only registered accounts have pending withdrawals" - ); - uint256 length = balances[account].pendingWithdrawals.length; - uint256[] memory values = new uint256[](length); - uint256[] memory timestamps = new uint256[](length); - for (uint256 i = 0; i < length; i = i.add(1)) { - PendingWithdrawal memory pendingWithdrawal = (balances[account].pendingWithdrawals[i]); - values[i] = pendingWithdrawal.value; - timestamps[i] = pendingWithdrawal.timestamp; - } - return (values, timestamps); - } - - /** - * @notice Returns the pending withdrawal at a given index for a given account. - * @param account The address of the account. - * @param index The index of the pending withdrawal. - * @return The value of the pending withdrawal. - * @return The timestamp of the pending withdrawal. - */ - function getPendingWithdrawal(address account, uint256 index) - external - view - returns (uint256, uint256) - { - require( - getAccounts().isAccount(account), - "Unknown account: only registered accounts have pending withdrawals" - ); - require(index < balances[account].pendingWithdrawals.length, "Bad pending withdrawal index"); - PendingWithdrawal memory pendingWithdrawal = (balances[account].pendingWithdrawals[index]); - - return (pendingWithdrawal.value, pendingWithdrawal.timestamp); - } - - /** - * @notice Returns the number of pending withdrawals for the specified account. - * @param account The address of the account. - * @return The count of pending withdrawals. - */ - function getTotalPendingWithdrawalsCount(address account) external view returns (uint256) { - return balances[account].pendingWithdrawals.length; - } - - /** - * @notice Returns the total amount to withdraw from unlocked gold for an account. - * @param account The address of the account. - * @return Total amount to withdraw. - */ - function getTotalPendingWithdrawals(address account) external view returns (uint256) { - uint256 pendingWithdrawalSum = 0; - PendingWithdrawal[] memory withdrawals = balances[account].pendingWithdrawals; - for (uint256 i = 0; i < withdrawals.length; i = i.add(1)) { - pendingWithdrawalSum = pendingWithdrawalSum.add(withdrawals[i].value); - } - return pendingWithdrawalSum; - } - - function getSlashingWhitelist() external view returns (bytes32[] memory) { - return slashingWhitelist; - } - - /** - * @notice Deletes a pending withdrawal. - * @param list The list of pending withdrawals from which to delete. - * @param index The index of the pending withdrawal to delete. - */ - function deletePendingWithdrawal(PendingWithdrawal[] storage list, uint256 index) private { - uint256 lastIndex = list.length.sub(1); - list[index] = list[lastIndex]; - list.length = lastIndex; - } - - /** - * @notice Adds `slasher` to whitelist of approved slashing addresses. - * @param slasherIdentifier Identifier to whitelist. - */ - function addSlasher(string calldata slasherIdentifier) external onlyOwner { - bytes32 keyBytes = keccak256(abi.encodePacked(slasherIdentifier)); - require(registry.getAddressFor(keyBytes) != address(0), "Identifier is not registered"); - require(!slashingMap[keyBytes], "Cannot add slasher ID twice."); - slashingWhitelist.push(keyBytes); - slashingMap[keyBytes] = true; - emit SlasherWhitelistAdded(slasherIdentifier); - } - - /** - * @notice Removes `slasher` from whitelist of approved slashing addresses. - * @param slasherIdentifier Identifier to remove from whitelist. - * @param index Index of the provided identifier in slashingWhiteList array. - */ - function removeSlasher(string calldata slasherIdentifier, uint256 index) external onlyOwner { - bytes32 keyBytes = keccak256(abi.encodePacked(slasherIdentifier)); - require(slashingMap[keyBytes], "Cannot remove slasher ID not yet added."); - require(index < slashingWhitelist.length, "Provided index exceeds whitelist bounds."); - require(slashingWhitelist[index] == keyBytes, "Index doesn't match identifier"); - slashingWhitelist[index] = slashingWhitelist[slashingWhitelist.length - 1]; - slashingWhitelist.pop(); - slashingMap[keyBytes] = false; - emit SlasherWhitelistRemoved(slasherIdentifier); - } - - /** - * @notice Slashes `account` by reducing its nonvoting locked gold by `penalty`. - * If there is not enough nonvoting locked gold to slash, calls into - * `Election.slashVotes` to slash the remaining gold. If `account` does not have - * `penalty` worth of locked gold, slashes `account`'s total locked gold. - * Also sends `reward` gold to the reporter, and penalty-reward to the Community Fund. - * @param account Address of account being slashed. - * @param penalty Amount to slash account. - * @param reporter Address of account reporting the slasher. - * @param reward Reward to give reporter. - * @param lessers The groups receiving fewer votes than i'th group, or 0 if the i'th group has - * the fewest votes of any validator group. - * @param greaters The groups receiving more votes than the i'th group, or 0 if the i'th group - * has the most votes of any validator group. - * @param indices The indices of the i'th group in `account`'s voting list. - * @dev Fails if `reward` is greater than `account`'s total locked gold. - */ - function slash( - address account, - uint256 penalty, - address reporter, - uint256 reward, - address[] calldata lessers, - address[] calldata greaters, - uint256[] calldata indices - ) external onlySlasher { - uint256 maxSlash = Math.min(penalty, getAccountTotalLockedGold(account)); - require(maxSlash >= reward, "reward cannot exceed penalty."); - // `reporter` receives the reward in locked CELO, so it must be given to an account - // There is no reward for slashing via the GovernanceSlasher, and `reporter` - // is set to 0x0. - if (reporter != address(0)) { - reporter = getAccounts().signerToAccount(reporter); - } - // Local scoping is required to avoid Solc "stack too deep" error from too many locals. - { - uint256 nonvotingBalance = balances[account].nonvoting; - uint256 difference = 0; - // If not enough nonvoting, revoke the difference - if (nonvotingBalance < maxSlash) { - difference = maxSlash.sub(nonvotingBalance); - require( - getElection().forceDecrementVotes(account, difference, lessers, greaters, indices) == - difference, - "Cannot revoke enough voting gold." - ); - } - // forceDecrementVotes does not increment nonvoting account balance, so we can't double count - _decrementNonvotingAccountBalance(account, maxSlash.sub(difference)); - _incrementNonvotingAccountBalance(reporter, reward); - } - address communityFund = registry.getAddressForOrDie(GOVERNANCE_REGISTRY_ID); - address payable communityFundPayable = address(uint160(communityFund)); - require(maxSlash.sub(reward) <= address(this).balance, "Inconsistent balance"); - communityFundPayable.sendValue(maxSlash.sub(reward)); - emit AccountSlashed(account, maxSlash, reporter, reward); - } -} diff --git a/packages/protocol/contracts/governance/Proposals.sol b/packages/protocol/contracts/governance/Proposals.sol deleted file mode 100644 index f5d57f4cb..000000000 --- a/packages/protocol/contracts/governance/Proposals.sol +++ /dev/null @@ -1,357 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "openzeppelin-solidity/contracts/utils/Address.sol"; -import "solidity-bytes-utils/contracts/BytesLib.sol"; - -import "../common/FixidityLib.sol"; - -/** - * @title A library operating on Celo Governance proposals. - */ -library Proposals { - using FixidityLib for FixidityLib.Fraction; - using SafeMath for uint256; - using BytesLib for bytes; - - enum Stage { None, Queued, Approval, Referendum, Execution, Expiration } - - enum VoteValue { None, Abstain, No, Yes } - - struct StageDurations { - uint256 approval; - uint256 referendum; - uint256 execution; - } - - struct VoteTotals { - uint256 yes; - uint256 no; - uint256 abstain; - } - - struct Transaction { - uint256 value; - address destination; - bytes data; - } - - struct Proposal { - address proposer; - uint256 deposit; - uint256 timestamp; - VoteTotals votes; - Transaction[] transactions; - bool approved; - uint256 networkWeight; - string descriptionUrl; - } - - /** - * @notice Constructs a proposal. - * @param proposal The proposal struct to be constructed. - * @param values The values of CELO to be sent in the proposed transactions. - * @param destinations The destination addresses of the proposed transactions. - * @param data The concatenated data to be included in the proposed transactions. - * @param dataLengths The lengths of each transaction's data. - * @param proposer The proposer. - * @param deposit The proposal deposit. - */ - function make( - Proposal storage proposal, - uint256[] memory values, - address[] memory destinations, - bytes memory data, - uint256[] memory dataLengths, - address proposer, - uint256 deposit - ) public { - require( - values.length == destinations.length && destinations.length == dataLengths.length, - "Array length mismatch" - ); - uint256 transactionCount = values.length; - - proposal.proposer = proposer; - proposal.deposit = deposit; - // solhint-disable-next-line not-rely-on-time - proposal.timestamp = now; - - uint256 dataPosition = 0; - delete proposal.transactions; - for (uint256 i = 0; i < transactionCount; i = i.add(1)) { - proposal.transactions.push( - Transaction(values[i], destinations[i], data.slice(dataPosition, dataLengths[i])) - ); - dataPosition = dataPosition.add(dataLengths[i]); - } - } - - function setDescriptionUrl(Proposal storage proposal, string memory descriptionUrl) internal { - require(bytes(descriptionUrl).length != 0, "Description url must have non-zero length"); - proposal.descriptionUrl = descriptionUrl; - } - - /** - * @notice Constructs a proposal for use in memory. - * @param values The values of CELO to be sent in the proposed transactions. - * @param destinations The destination addresses of the proposed transactions. - * @param data The concatenated data to be included in the proposed transactions. - * @param dataLengths The lengths of each transaction's data. - * @param proposer The proposer. - * @param deposit The proposal deposit. - */ - function makeMem( - uint256[] memory values, - address[] memory destinations, - bytes memory data, - uint256[] memory dataLengths, - address proposer, - uint256 deposit - ) internal view returns (Proposal memory) { - require( - values.length == destinations.length && destinations.length == dataLengths.length, - "Array length mismatch" - ); - uint256 transactionCount = values.length; - - Proposal memory proposal; - proposal.proposer = proposer; - proposal.deposit = deposit; - // solhint-disable-next-line not-rely-on-time - proposal.timestamp = now; - - uint256 dataPosition = 0; - proposal.transactions = new Transaction[](transactionCount); - for (uint256 i = 0; i < transactionCount; i = i.add(1)) { - proposal.transactions[i] = Transaction( - values[i], - destinations[i], - data.slice(dataPosition, dataLengths[i]) - ); - dataPosition = dataPosition.add(dataLengths[i]); - } - return proposal; - } - - /** - * @notice Adds or changes a vote on a proposal. - * @param proposal The proposal struct. - * @param previousYesVotes The previous yes votes weight. - * @param previousNoVotes The previous no votes weight. - * @param previousAbstainVotes The previous abstain votes weight. - * @param yesVotes The current yes votes weight. - * @param noVotes The current no votes weight. - * @param abstainVotes The current abstain votes weight. - */ - function updateVote( - Proposal storage proposal, - uint256 previousYesVotes, - uint256 previousNoVotes, - uint256 previousAbstainVotes, - uint256 yesVotes, - uint256 noVotes, - uint256 abstainVotes - ) public { - // Subtract previous vote. - proposal.votes.yes = proposal.votes.yes.sub(previousYesVotes); - proposal.votes.no = proposal.votes.no.sub(previousNoVotes); - proposal.votes.abstain = proposal.votes.abstain.sub(previousAbstainVotes); - - // Add new vote. - proposal.votes.yes = proposal.votes.yes.add(yesVotes); - proposal.votes.no = proposal.votes.no.add(noVotes); - proposal.votes.abstain = proposal.votes.abstain.add(abstainVotes); - } - - /** - * @notice Executes the proposal. - * @param proposal The proposal struct. - * @dev Reverts if any transaction fails. - */ - function execute(Proposal storage proposal) public { - executeTransactions(proposal.transactions); - } - - /** - * @notice Executes the proposal. - * @param proposal The proposal struct. - * @dev Reverts if any transaction fails. - */ - function executeMem(Proposal memory proposal) internal { - executeTransactions(proposal.transactions); - } - - function executeTransactions(Transaction[] memory transactions) internal { - for (uint256 i = 0; i < transactions.length; i = i.add(1)) { - require( - externalCall( - transactions[i].destination, - transactions[i].value, - transactions[i].data.length, - transactions[i].data - ), - "Proposal execution failed" - ); - } - } - - /** - * @notice Computes the support ratio for a proposal with the quorum condition: - * If the total number of votes (yes + no + abstain) is less than the required number of votes, - * "no" votes are added to increase particiption to this level. The ratio of yes / (yes + no) - * votes is returned. - * @param proposal The proposal struct. - * @param quorum The minimum participation at which "no" votes are not added. - * @return The support ratio with the quorum condition. - */ - function getSupportWithQuorumPadding( - Proposal storage proposal, - FixidityLib.Fraction memory quorum - ) internal view returns (FixidityLib.Fraction memory) { - uint256 yesVotes = proposal.votes.yes; - if (yesVotes == 0) { - return FixidityLib.newFixed(0); - } - uint256 noVotes = proposal.votes.no; - uint256 totalVotes = yesVotes.add(noVotes).add(proposal.votes.abstain); - uint256 requiredVotes = quorum - .multiply(FixidityLib.newFixed(proposal.networkWeight)) - .fromFixed(); - if (requiredVotes > totalVotes) { - noVotes = noVotes.add(requiredVotes.sub(totalVotes)); - } - return FixidityLib.newFixedFraction(yesVotes, yesVotes.add(noVotes)); - } - - /** - * @notice Returns the number of votes cast on the proposal over the total number - * of votes in the network as a fraction. - * @param proposal The proposal struct. - * @return The participation of the proposal. - */ - function getParticipation(Proposal storage proposal) - internal - view - returns (FixidityLib.Fraction memory) - { - uint256 totalVotes = proposal.votes.yes.add(proposal.votes.no).add(proposal.votes.abstain); - return FixidityLib.newFixedFraction(totalVotes, proposal.networkWeight); - } - - /** - * @notice Returns a specified transaction in a proposal. - * @param proposal The proposal struct. - * @param index The index of the specified transaction in the proposal's transaction list. - * @return Transaction value. - * @return Transaction destination. - * @return Transaction data. - */ - function getTransaction(Proposal storage proposal, uint256 index) - public - view - returns (uint256, address, bytes memory) - { - require(index < proposal.transactions.length, "getTransaction: bad index"); - Transaction storage transaction = proposal.transactions[index]; - return (transaction.value, transaction.destination, transaction.data); - } - - /** - * @notice Returns an unpacked proposal struct with its transaction count. - * @param proposal The proposal struct. - * @return proposer - * @return deposit - * @return timestamp - * @return transaction Transaction count. - * @return description Description url. - * @return networkWeight Network weight. - */ - function unpack(Proposal storage proposal) - internal - view - returns (address, uint256, uint256, uint256, string storage, uint256, bool) - { - return ( - proposal.proposer, - proposal.deposit, - proposal.timestamp, - proposal.transactions.length, - proposal.descriptionUrl, - proposal.networkWeight, - proposal.approved - ); - } - - /** - * @notice Returns the referendum vote totals for a proposal. - * @param proposal The proposal struct. - * @return The yes vote totals. - * @return The no vote totals. - * @return The abstain vote totals. - */ - function getVoteTotals(Proposal storage proposal) - internal - view - returns (uint256, uint256, uint256) - { - return (proposal.votes.yes, proposal.votes.no, proposal.votes.abstain); - } - - /** - * @notice Returns whether or not a proposal has been approved. - * @param proposal The proposal struct. - * @return Whether or not the proposal has been approved. - */ - function isApproved(Proposal storage proposal) internal view returns (bool) { - return proposal.approved; - } - - /** - * @notice Returns whether or not a proposal exists. - * @param proposal The proposal struct. - * @return Whether or not the proposal exists. - */ - function exists(Proposal storage proposal) internal view returns (bool) { - return proposal.timestamp > 0; - } - - // call has been separated into its own function in order to take advantage - // of the Solidity's code generator to produce a loop that copies tx.data into memory. - /** - * @notice Executes a function call. - * @param value The value of CELO to be sent with the function call. - * @param destination The destination address of the function call. - * @param dataLength The length of the data to be included in the function call. - * @param data The data to be included in the function call. - */ - function externalCall(address destination, uint256 value, uint256 dataLength, bytes memory data) - private - returns (bool) - { - bool result; - - if (dataLength > 0) require(Address.isContract(destination), "Invalid contract address"); - - /* solhint-disable no-inline-assembly */ - assembly { - /* solhint-disable max-line-length */ - let x := mload(0x40) // "Allocate" memory for output (0x40 is where "free memory" pointer is stored by convention) - let d := add(data, 32) // First 32 bytes are the padded length of data, so exclude that - result := call( - sub(gas, 34710), // 34710 is the value that solidity is currently emitting - // It includes callGas (700) + callVeryLow (3, to pay for SUB) + callValueTransferGas (9000) + - // callNewAccountGas (25000, in case the destination address does not exist and needs creating) - destination, - value, - d, - dataLength, // Size of the input (in bytes) - this is what fixes the padding problem - x, - 0 // Output is ignored, therefore the output size is zero - ) - /* solhint-enable max-line-length */ - } - /* solhint-enable no-inline-assembly */ - return result; - } -} diff --git a/packages/protocol/contracts/governance/ReleaseGold.sol b/packages/protocol/contracts/governance/ReleaseGold.sol deleted file mode 100644 index d11f9e9c9..000000000 --- a/packages/protocol/contracts/governance/ReleaseGold.sol +++ /dev/null @@ -1,804 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/Math.sol"; -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; -import "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol"; -import "openzeppelin-solidity/contracts/utils/Address.sol"; - -import "./interfaces/IReleaseGold.sol"; - -import "../common/FixidityLib.sol"; -import "../common/libraries/ReentrancyGuard.sol"; -import "../common/Initializable.sol"; -import "../common/UsingRegistry.sol"; - -contract ReleaseGold is UsingRegistry, ReentrancyGuard, IReleaseGold, Initializable { - using SafeMath for uint256; - using FixidityLib for FixidityLib.Fraction; - using Address for address payable; // prettier-ignore - - struct ReleaseSchedule { - // Timestamp (in UNIX time) that releasing begins. - uint256 releaseStartTime; - // Timestamp (in UNIX time) of the releasing cliff. - uint256 releaseCliff; - // Number of release periods. - uint256 numReleasePeriods; - // Duration (in seconds) of one period. - uint256 releasePeriod; - // Amount that is to be released per period. - uint256 amountReleasedPerPeriod; - } - - struct RevocationInfo { - // Indicates if the contract is revocable. - bool revocable; - // Indicates if the contract can expire `EXPIRATION_TIME` after releasing finishes. - bool canExpire; - // Released gold instance balance at time of revocation. - uint256 releasedBalanceAtRevoke; - // The time at which the release schedule was revoked. - uint256 revokeTime; - } - - // uint256(-1) == 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - uint256 internal constant MAX_UINT = uint256(-1); - - // Duration (in seconds) after gold is fully released - // when gold should be switched back to control of releaseOwner. - // 2 years - uint256 public constant EXPIRATION_TIME = 63072000; - - // Beneficiary of the CELO released in this contract. - address payable public beneficiary; - - // Address capable of (where applicable) revoking, setting the liquidity provision, and - // adjusting the maximum withdrawal amount. - address public releaseOwner; - - // Address that receives refunded gold if contract is revoked. - address payable public refundAddress; - - // Indicates how much of the released amount has been withdrawn so far. - uint256 public totalWithdrawn; - - // Indicates the maximum gold currently available for distribution, regardless of schedule. - // Only settable by the `releaseOwner` address, subject to grant conditions. - uint256 public maxDistribution; - - // Indicates if the schedule contains a liquidity provision that has not yet been met. - // Only settable by the `releaseOwner` address, subject to grant conditions. - bool public liquidityProvisionMet; - - // Indicates if this schedule's unreleased gold can be used for validating. - bool public canValidate; - - // Indicates if this schedule's unreleased gold can be used for voting. - bool public canVote; - - // Public struct housing params pertaining to releasing gold. - ReleaseSchedule public releaseSchedule; - - // Public struct housing params pertaining to revocation. - RevocationInfo public revocationInfo; - - event ReleaseGoldInstanceCreated(address indexed beneficiary, address indexed atAddress); - event ReleaseScheduleRevoked(uint256 revokeTimestamp, uint256 releasedBalanceAtRevoke); - event ReleaseGoldInstanceDestroyed(address indexed beneficiary, address indexed atAddress); - event DistributionLimitSet(address indexed beneficiary, uint256 maxDistribution); - event LiquidityProvisionSet(address indexed beneficiary); - event CanExpireSet(bool canExpire); - event BeneficiarySet(address indexed beneficiary); - - modifier onlyReleaseOwner() { - require(msg.sender == releaseOwner, "Sender must be the registered releaseOwner address"); - _; - } - - modifier onlyBeneficiary() { - require(msg.sender == beneficiary, "Sender must be the registered beneficiary address"); - _; - } - - modifier onlyRevoked() { - require(isRevoked(), "Release schedule instance must have already been revoked"); - _; - } - - modifier onlyRevocable() { - require(revocationInfo.revocable, "Release schedule instance must be revocable"); - _; - } - - modifier onlyCanVote() { - require(canVote, "Release Gold contract does not have permission to vote"); - _; - } - - modifier onlyCanValidate() { - require(canValidate, "Release Gold contract does not have permission to validate"); - _; - } - - modifier onlyReleaseOwnerAndRevoked() { - require( - msg.sender == releaseOwner && isRevoked(), - "Sender must be the releaseOwner and state must be revoked" - ); - _; - } - - modifier onlyBeneficiaryAndNotRevoked() { - require( - msg.sender == beneficiary && !isRevoked(), - "Sender must be the beneficiary and state must not be revoked" - ); - _; - } - - modifier onlyWhenInProperState() { - bool isRevoked = isRevoked(); - require( - (msg.sender == releaseOwner && isRevoked) || (msg.sender == beneficiary && !isRevoked), - "Must be called by releaseOwner when revoked or beneficiary before revocation" - ); - _; - } - - modifier onlyExpired() { - require(revocationInfo.canExpire, "Contract must be expirable"); - uint256 releaseEndTime = releaseSchedule.releaseStartTime.add( - releaseSchedule.numReleasePeriods.mul(releaseSchedule.releasePeriod) - ); - require( - block.timestamp >= releaseEndTime.add(EXPIRATION_TIME), - "`EXPIRATION_TIME` must have passed after the end of releasing" - ); - _; - } - - /** - * @notice Sets initialized == true on implementation contracts - * @param test Set to true to skip implementation initialization - */ - constructor(bool test) public Initializable(test) {} - - function isFunded() public view returns (bool) { - // grants which have already released are considered funded for backwards compatibility - return - getCurrentReleasedTotalAmount() > 0 || - address(this).balance >= - releaseSchedule.amountReleasedPerPeriod.mul(releaseSchedule.numReleasePeriods); - } - - function() external payable {} - - /** - * @notice Wrapper function for stable token transfer function. - */ - function transfer(address to, uint256 value) external onlyWhenInProperState { - IERC20(registry.getAddressForOrDie(STABLE_TOKEN_REGISTRY_ID)).transfer(to, value); - } - - /** - * @notice Wrapper function for any ERC-20 transfer function. - * @dev Protects against celo balance changes. - */ - function genericTransfer(address erc20, address to, uint256 value) - external - onlyWhenInProperState - { - require( - erc20 != registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID), - "Transfer must not target celo balance" - ); - SafeERC20.safeTransfer(IERC20(erc20), to, value); - } - - /** - * @notice A constructor for initialising a new instance of a Releasing Schedule contract. - * @param releaseStartTime The time (in Unix time) at which point releasing starts. - * @param releaseCliffTime Duration (in seconds) after `releaseStartTime` of the golds' cliff. - * @param numReleasePeriods Number of releasing periods. - * @param releasePeriod Duration (in seconds) of each release period. - * @param amountReleasedPerPeriod The released gold amount per period. - * @param revocable Whether the release schedule is revocable or not. - * @param _beneficiary Address of the beneficiary to whom released tokens are transferred. - * @param _releaseOwner Address capable of revoking, setting the liquidity provision - * and setting the withdrawal amount. - * 0x0 if grant is not subject to these operations. - * @param _refundAddress Address that receives refunded funds if contract is revoked. - * 0x0 if contract is not revocable. - * @param subjectToLiquidityProvision If this schedule is subject to a liquidity provision. - * @param initialDistributionRatio Amount in range [0, 1000] (3 significant figures) - * indicating % of total balance available for distribution. - * @param _canValidate If this schedule's gold can be used for validating. - * @param _canVote If this schedule's gold can be used for voting. - * @param registryAddress Address of the deployed contracts registry. - */ - function initialize( - uint256 releaseStartTime, - uint256 releaseCliffTime, - uint256 numReleasePeriods, - uint256 releasePeriod, - uint256 amountReleasedPerPeriod, - bool revocable, - address payable _beneficiary, - address _releaseOwner, - address payable _refundAddress, - bool subjectToLiquidityProvision, - uint256 initialDistributionRatio, - bool _canValidate, - bool _canVote, - address registryAddress - ) external initializer { - _transferOwnership(msg.sender); - releaseSchedule.numReleasePeriods = numReleasePeriods; - releaseSchedule.amountReleasedPerPeriod = amountReleasedPerPeriod; - releaseSchedule.releasePeriod = releasePeriod; - releaseSchedule.releaseCliff = releaseStartTime.add(releaseCliffTime); - releaseSchedule.releaseStartTime = releaseStartTime; - // Expiry is opt-in for folks who can validate, opt-out for folks who cannot. - // This is because folks who are running Validators or Groups are likely to want to keep - // CELO in the ReleaseGold contract even after it becomes withdrawable. - revocationInfo.canExpire = !canValidate; - require(releaseSchedule.numReleasePeriods >= 1, "There must be at least one releasing period"); - require( - releaseSchedule.amountReleasedPerPeriod > 0, - "The released amount per period must be greater than zero" - ); - require( - _beneficiary != address(0), - "The release schedule beneficiary cannot be the zero addresss" - ); - require(registryAddress != address(0), "The registry address cannot be the zero address"); - require(!(revocable && _canValidate), "Revocable contracts cannot validate"); - require(initialDistributionRatio <= 1000, "Initial distribution ratio out of bounds"); - require( - (revocable && _refundAddress != address(0)) || (!revocable && _refundAddress == address(0)), - "If contract is revocable there must be an address to refund" - ); - setRegistry(registryAddress); - _setBeneficiary(_beneficiary); - revocationInfo.revocable = revocable; - releaseOwner = _releaseOwner; - refundAddress = _refundAddress; - - if (initialDistributionRatio < 1000) { - // Cannot use `getTotalBalance()` here because the factory has not yet sent the gold. - uint256 totalGrant = releaseSchedule.amountReleasedPerPeriod.mul( - releaseSchedule.numReleasePeriods - ); - // Initial ratio is expressed to 3 significant figures: [0, 1000]. - maxDistribution = totalGrant.mul(initialDistributionRatio).div(1000); - } else { - maxDistribution = MAX_UINT; - } - liquidityProvisionMet = (subjectToLiquidityProvision) ? false : true; - canValidate = _canValidate; - canVote = _canVote; - emit ReleaseGoldInstanceCreated(beneficiary, address(this)); - } - - /** - * @notice Returns if the release schedule has been revoked or not. - * @return True if instance revoked. - */ - function isRevoked() public view returns (bool) { - return revocationInfo.revokeTime > 0; - } - - /** - * @notice Controls if the liquidity provision has been met, allowing gold to be withdrawn. - */ - function setLiquidityProvision() external onlyReleaseOwner { - require(!liquidityProvisionMet, "Liquidity provision has already been set"); - liquidityProvisionMet = true; - emit LiquidityProvisionSet(beneficiary); - } - - /** - * @notice Controls if the contract can be expired. - * @param _canExpire If the contract is expirable. - */ - function setCanExpire(bool _canExpire) external onlyBeneficiary { - require( - revocationInfo.canExpire != _canExpire, - "Expiration flag is already set to desired value" - ); - revocationInfo.canExpire = _canExpire; - emit CanExpireSet(revocationInfo.canExpire); - } - - /** - * @notice Controls the maximum distribution ratio. - * Calculates `distributionRatio`/1000 of current `totalBalance()` - * and sets this value as the maximum allowed gold to be currently withdrawn. - * @param distributionRatio Amount in range [0, 1000] (3 significant figures) - * indicating % of total balance available for distribution. - */ - function setMaxDistribution(uint256 distributionRatio) external onlyReleaseOwner { - require(distributionRatio <= 1000, "Max distribution ratio must be within bounds"); - require( - maxDistribution != MAX_UINT, - "Cannot set max distribution lower if already set to 1000" - ); - // If ratio is 1000, we set maxDistribution to maxUint to account for future rewards. - if (distributionRatio == 1000) { - maxDistribution = MAX_UINT; - } else { - uint256 totalBalance = getTotalBalance(); - require(totalBalance > 0, "Do not set max distribution before factory sends the gold"); - maxDistribution = totalBalance.mul(distributionRatio).div(1000); - } - emit DistributionLimitSet(beneficiary, maxDistribution); - } - - /** - * @notice Sets the beneficiary of the instance - * @param newBeneficiary The address of the new beneficiary - */ - function setBeneficiary(address payable newBeneficiary) external onlyOwner { - _setBeneficiary(newBeneficiary); - } - - /** - * @notice Sets the beneficiary of the instance - * @param newBeneficiary The address of the new beneficiary - */ - function _setBeneficiary(address payable newBeneficiary) private { - require(newBeneficiary != address(0x0), "Can't set the beneficiary to the zero address"); - beneficiary = newBeneficiary; - emit BeneficiarySet(newBeneficiary); - } - - /** - * @notice Transfers gold from this release schedule instance to the beneficiary. - * @param amount The requested gold amount. - */ - function withdraw(uint256 amount) external nonReentrant onlyBeneficiary { - require(amount > 0, "Requested withdrawal amount must be greater than zero"); - require(liquidityProvisionMet, "Requested withdrawal before liquidity provision is met"); - - uint256 releasedAmount; - if (isRevoked()) { - releasedAmount = revocationInfo.releasedBalanceAtRevoke; - } else { - releasedAmount = getCurrentReleasedTotalAmount(); - } - - require( - releasedAmount.sub(totalWithdrawn) >= amount, - "Requested amount is greater than available released funds" - ); - require( - maxDistribution >= totalWithdrawn.add(amount), - "Requested amount exceeds current alloted maximum distribution" - ); - require( - getRemainingUnlockedBalance() >= amount, - "Insufficient unlocked balance to withdraw amount" - ); - totalWithdrawn = totalWithdrawn.add(amount); - beneficiary.sendValue(amount); - if (getRemainingTotalBalance() == 0) { - emit ReleaseGoldInstanceDestroyed(beneficiary, address(this)); - selfdestruct(refundAddress); - } - } - - /** - * @notice Refund the releaseOwner and beneficiary after the release schedule has been revoked. - */ - function refundAndFinalize() external nonReentrant onlyReleaseOwnerAndRevoked { - require(getRemainingLockedBalance() == 0, "Total gold balance must be unlocked"); - uint256 beneficiaryAmount = revocationInfo.releasedBalanceAtRevoke.sub(totalWithdrawn); - require(address(this).balance >= beneficiaryAmount, "Inconsistent balance"); - beneficiary.sendValue(beneficiaryAmount); - uint256 revokerAmount = getRemainingUnlockedBalance(); - refundAddress.sendValue(revokerAmount); - emit ReleaseGoldInstanceDestroyed(beneficiary, address(this)); - selfdestruct(refundAddress); - } - - /** - * @notice Revoke the future release schedule. - */ - function revoke() external nonReentrant onlyReleaseOwner onlyRevocable { - require(!isRevoked(), "Release schedule instance must not already be revoked"); - revocationInfo.revokeTime = block.timestamp; - revocationInfo.releasedBalanceAtRevoke = getCurrentReleasedTotalAmount(); - emit ReleaseScheduleRevoked(revocationInfo.revokeTime, revocationInfo.releasedBalanceAtRevoke); - } - - /** - * @notice Mark the contract as expired, freeing all remaining gold for refund to `refundAddress` - * @dev Only callable `EXPIRATION_TIME` after the final gold release. - */ - function expire() external nonReentrant onlyReleaseOwner onlyExpired { - require(!isRevoked(), "Release schedule instance must not already be revoked"); - revocationInfo.revokeTime = block.timestamp; - revocationInfo.releasedBalanceAtRevoke = totalWithdrawn; - emit ReleaseScheduleRevoked(revocationInfo.revokeTime, totalWithdrawn); - } - - /** - * @notice Calculates the total balance of the release schedule instance including withdrawals. - * @return The total released instance gold balance. - * @dev The returned amount may vary over time due to locked gold rewards. - */ - function getTotalBalance() public view returns (uint256) { - return getRemainingUnlockedBalance().add(getRemainingLockedBalance()).add(totalWithdrawn); - } - - /** - * @notice Calculates the sum of locked and unlocked gold in the release schedule instance. - * @return The remaining total released instance gold balance. - * @dev The returned amount may vary over time due to locked gold rewards. - */ - function getRemainingTotalBalance() public view returns (uint256) { - return getRemainingUnlockedBalance().add(getRemainingLockedBalance()); - } - - /** - * @notice Calculates remaining unlocked gold balance in the release schedule instance. - * @return The available unlocked release schedule instance gold balance. - */ - function getRemainingUnlockedBalance() public view returns (uint256) { - return address(this).balance; - } - - /** - * @notice Calculates remaining locked gold balance in the release schedule instance. - * The returned amount also includes pending withdrawals to maintain consistent releases. - * Return 0 if address of caller is not an account. - * @return The remaining locked gold of the release schedule instance. - * @dev The returned amount may vary over time due to locked gold rewards. - */ - function getRemainingLockedBalance() public view returns (uint256) { - if (getAccounts().isAccount(address(this))) { - ILockedGold lockedGold = getLockedGold(); - uint256 pendingWithdrawalSum = lockedGold.getTotalPendingWithdrawals(address(this)); - return lockedGold.getAccountTotalLockedGold(address(this)).add(pendingWithdrawalSum); - } - return 0; - } - - /** - * @dev Calculates the total amount that has already released up to now. - * @return The already released amount up to the point of call. - * @dev The returned amount may vary over time due to locked gold rewards. - */ - function getCurrentReleasedTotalAmount() public view returns (uint256) { - if (block.timestamp < releaseSchedule.releaseCliff || !liquidityProvisionMet) { - return 0; - } - uint256 totalBalance = getTotalBalance(); - - if ( - block.timestamp >= - releaseSchedule.releaseStartTime.add( - releaseSchedule.numReleasePeriods.mul(releaseSchedule.releasePeriod) - ) - ) { - return totalBalance; - } - - uint256 timeSinceStart = block.timestamp.sub(releaseSchedule.releaseStartTime); - uint256 periodsSinceStart = timeSinceStart.div(releaseSchedule.releasePeriod); - return totalBalance.mul(periodsSinceStart).div(releaseSchedule.numReleasePeriods); - } - - /** - * @notice A wrapper function for the lock gold method. - * @param value The value of gold to be locked. - */ - function lockGold(uint256 value) external nonReentrant onlyBeneficiaryAndNotRevoked { - getLockedGold().lock.gas(gasleft()).value(value)(); - } - - /** - * @notice A wrapper function for the unlock gold method function. - * @param value The value of gold to be unlocked for the release schedule instance. - */ - function unlockGold(uint256 value) external nonReentrant onlyWhenInProperState { - getLockedGold().unlock(value); - } - - /** - * @notice A wrapper function for the relock locked gold method function. - * @param index The index of the pending locked gold withdrawal. - * @param value The value of gold to be relocked for the release schedule instance. - */ - function relockGold(uint256 index, uint256 value) - external - nonReentrant - onlyBeneficiaryAndNotRevoked - { - getLockedGold().relock(index, value); - } - - /** - * @notice A wrapper function for the withdraw locked gold method function. - * @param index The index of the pending locked gold withdrawal. - * @dev The amount shall be withdrawn back to the release schedule instance. - */ - function withdrawLockedGold(uint256 index) external nonReentrant onlyWhenInProperState { - getLockedGold().withdraw(index); - } - - /** - * @notice Funds a signer address so that transaction fees can be paid. - * @param signer The signer address to fund. - * @dev Note that this effectively decreases the total balance by 1 CELO. - */ - function fundSigner(address payable signer) private { - // Fund signer account with 1 CELO. - uint256 value = 1 ether; - require(address(this).balance >= value, "no available CELO to fund signer"); - signer.sendValue(value); - require(getRemainingTotalBalance() > 0, "no remaining balance"); - } - - /** - * @notice A wrapper function for the authorize vote signer account method. - * @param signer The address of the signing key to authorize. - * @param v The recovery id of the incoming ECDSA signature. - * @param r Output value r of the ECDSA signature. - * @param s Output value s of the ECDSA signature. - * @dev The v,r and s signature should be signed by the authorized signer - * key, with the ReleaseGold contract address as the message. - */ - function authorizeVoteSigner(address payable signer, uint8 v, bytes32 r, bytes32 s) - external - nonReentrant - onlyCanVote - onlyWhenInProperState - { - // If no previous signer has been authorized, fund the new signer so that tx fees can be paid. - if (getAccounts().getVoteSigner(address(this)) == address(this)) { - fundSigner(signer); - } - getAccounts().authorizeVoteSigner(signer, v, r, s); - } - - /** - * @notice A wrapper function for the authorize validator signer account method. - * @param signer The address of the signing key to authorize. - * @param v The recovery id of the incoming ECDSA signature. - * @param r Output value r of the ECDSA signature. - * @param s Output value s of the ECDSA signature. - * @dev The v,r and s signature should be signed by the authorized signer - * key, with the ReleaseGold contract address as the message. - */ - function authorizeValidatorSigner(address payable signer, uint8 v, bytes32 r, bytes32 s) - external - nonReentrant - onlyCanValidate - onlyWhenInProperState - { - // If no previous signer has been authorized, fund the new signer so that tx fees can be paid. - if (getAccounts().getValidatorSigner(address(this)) == address(this)) { - fundSigner(signer); - } - getAccounts().authorizeValidatorSigner(signer, v, r, s); - } - - /** - * @notice A wrapper function for the authorize validator signer with public key account method. - * @param signer The address of the signing key to authorize. - * @param v The recovery id of the incoming ECDSA signature. - * @param r Output value r of the ECDSA signature. - * @param s Output value s of the ECDSA signature. - * @param ecdsaPublicKey The ECDSA public key corresponding to `signer`. - * @dev The v,r and s signature should be signed by the authorized signer - * key, with the ReleaseGold contract address as the message. - */ - function authorizeValidatorSignerWithPublicKey( - address payable signer, - uint8 v, - bytes32 r, - bytes32 s, - bytes calldata ecdsaPublicKey - ) external nonReentrant onlyCanValidate onlyWhenInProperState { - // If no previous signer has been authorized, fund the new signer so that tx fees can be paid. - if (getAccounts().getValidatorSigner(address(this)) == address(this)) { - fundSigner(signer); - } - getAccounts().authorizeValidatorSignerWithPublicKey(signer, v, r, s, ecdsaPublicKey); - } - - /** - * @notice A wrapper function for the authorize validator signer with keys account method. - * @param signer The address of the signing key to authorize. - * @param v The recovery id of the incoming ECDSA signature. - * @param r Output value r of the ECDSA signature. - * @param s Output value s of the ECDSA signature. - * @param ecdsaPublicKey The ECDSA public key corresponding to `signer`. - * @param blsPublicKey The BLS public key that the validator is using for consensus, should pass - * proof of possession. 96 bytes. - * @param blsPop The BLS public key proof-of-possession, which consists of a signature on the - * account address. 48 bytes. - * @dev The v,r and s signature should be signed by the authorized signer - * key, with the ReleaseGold contract address as the message. - */ - function authorizeValidatorSignerWithKeys( - address payable signer, - uint8 v, - bytes32 r, - bytes32 s, - bytes calldata ecdsaPublicKey, - bytes calldata blsPublicKey, - bytes calldata blsPop - ) external nonReentrant onlyCanValidate onlyWhenInProperState { - // If no previous signer has been authorized, fund the new signer so that tx fees can be paid. - if (getAccounts().getValidatorSigner(address(this)) == address(this)) { - fundSigner(signer); - } - getAccounts().authorizeValidatorSignerWithKeys( - signer, - v, - r, - s, - ecdsaPublicKey, - blsPublicKey, - blsPop - ); - } - - /** - * @notice A wrapper function for the authorize attestation signer account method. - * @param signer The address of the signing key to authorize. - * @param v The recovery id of the incoming ECDSA signature. - * @param r Output value r of the ECDSA signature. - * @param s Output value s of the ECDSA signature. - * @dev The v,r and s signature should be signed by the authorized signer - * key, with the ReleaseGold contract address as the message. - */ - function authorizeAttestationSigner(address payable signer, uint8 v, bytes32 r, bytes32 s) - external - nonReentrant - onlyCanValidate - onlyWhenInProperState - { - getAccounts().authorizeAttestationSigner(signer, v, r, s); - } - - /** - * @notice A convenience wrapper setter for the name, dataEncryptionKey - * and wallet address for an account. - * @param name A string to set as the name of the account. - * @param dataEncryptionKey secp256k1 public key for data encryption. Preferably compressed. - * @param walletAddress The wallet address to set for the account. - * @param v The recovery id of the incoming ECDSA signature. - * @param r Output value r of the ECDSA signature. - * @param s Output value s of the ECDSA signature. - * @dev Wallet address can be zero. This means that the owner of the wallet - * does not want to be paid directly without interaction, and instead wants users to - * contact them, using the data encryption key, and arrange a payment. - * @dev v, r, s constitute `signer`'s signature on `msg.sender` (unless the wallet address - * is 0x0 or msg.sender). - */ - function setAccount( - string calldata name, - bytes calldata dataEncryptionKey, - address walletAddress, - uint8 v, - bytes32 r, - bytes32 s - ) external onlyBeneficiaryAndNotRevoked { - getAccounts().setAccount(name, dataEncryptionKey, walletAddress, v, r, s); - } - - /** - * @notice A wrapper setter function for creating an account. - */ - function createAccount() external onlyCanVote onlyBeneficiaryAndNotRevoked { - require(getAccounts().createAccount(), "Account creation failed"); - } - - /** - * @notice A wrapper setter function for the name of an account. - * @param name A string to set as the name of the account. - */ - function setAccountName(string calldata name) external onlyBeneficiaryAndNotRevoked { - getAccounts().setName(name); - } - - /** - * @notice A wrapper setter function for the wallet address of an account. - * @param walletAddress The wallet address to set for the account. - * @param v The recovery id of the incoming ECDSA signature. - * @param r Output value r of the ECDSA signature. - * @param s Output value s of the ECDSA signature. - * @dev Wallet address can be zero. This means that the owner of the wallet - * does not want to be paid directly without interaction, and instead wants users to - * contact them, using the data encryption key, and arrange a payment. - * @dev v, r, s constitute `signer`'s signature on `msg.sender` (unless the wallet address - * is 0x0 or msg.sender). - */ - function setAccountWalletAddress(address walletAddress, uint8 v, bytes32 r, bytes32 s) - external - onlyBeneficiaryAndNotRevoked - { - getAccounts().setWalletAddress(walletAddress, v, r, s); - } - - /** - * @notice A wrapper setter function for the for the data encryption key - * and version of an account. - * @param dataEncryptionKey Secp256k1 public key for data encryption. - * Preferably compressed. - */ - function setAccountDataEncryptionKey(bytes calldata dataEncryptionKey) - external - onlyBeneficiaryAndNotRevoked - { - getAccounts().setAccountDataEncryptionKey(dataEncryptionKey); - } - - /** - * @notice A wrapper setter function for the metadata of an account. - * @param metadataURL The URL to access the metadata.. - */ - function setAccountMetadataURL(string calldata metadataURL) - external - onlyBeneficiaryAndNotRevoked - { - getAccounts().setMetadataURL(metadataURL); - } - - /** - * @notice Revokes `value` active votes for `group`. - * @param group The validator group to revoke votes from. - * @param value The number of votes to revoke. - * @param lesser The group receiving fewer votes than the group for which the vote was revoked, - * or 0 if that group has the fewest votes of any validator group. - * @param greater The group receiving more votes than the group for which the vote was revoked, - * or 0 if that group has the most votes of any validator group. - * @param index The index of the group in the account's voting list. - * @dev Fails if the account has not voted on a validator group. - */ - function revokeActive( - address group, - uint256 value, - address lesser, - address greater, - uint256 index - ) external nonReentrant onlyWhenInProperState { - getElection().revokeActive(group, value, lesser, greater, index); - } - - /** - * @notice Revokes `value` pending votes for `group`. - * @param group The validator group to revoke votes from. - * @param value The number of votes to revoke. - * @param lesser The group receiving fewer votes than the group for which the vote was revoked, - * or 0 if that group has the fewest votes of any validator group. - * @param greater The group receiving more votes than the group for which the vote was revoked, - * or 0 if that group has the most votes of any validator group. - * @param index The index of the group in the account's voting list. - * @dev Fails if the account has not voted on a validator group. - */ - function revokePending( - address group, - uint256 value, - address lesser, - address greater, - uint256 index - ) external nonReentrant onlyWhenInProperState { - getElection().revokePending(group, value, lesser, greater, index); - } - - /** - * @return The currently withdrawable release amount. - */ - function getWithdrawableAmount() public view returns (uint256) { - return - Math.min( - Math.min(maxDistribution, getCurrentReleasedTotalAmount()).sub(totalWithdrawn), - getRemainingUnlockedBalance() - ); - } -} diff --git a/packages/protocol/contracts/governance/ReleaseGoldMultiSig.sol b/packages/protocol/contracts/governance/ReleaseGoldMultiSig.sol deleted file mode 100644 index 8ba8f46e5..000000000 --- a/packages/protocol/contracts/governance/ReleaseGoldMultiSig.sol +++ /dev/null @@ -1,12 +0,0 @@ -pragma solidity ^0.5.13; - -import "../common/MultiSig.sol"; - -/* solhint-disable no-empty-blocks */ -contract ReleaseGoldMultiSig is MultiSig { - /** - * @notice Sets initialized == true on implementation contracts - * @param test Set to true to skip implementation initialization - */ - constructor(bool test) public MultiSig(test) {} -} diff --git a/packages/protocol/contracts/governance/SlasherUtil.sol b/packages/protocol/contracts/governance/SlasherUtil.sol deleted file mode 100644 index bb8df67f7..000000000 --- a/packages/protocol/contracts/governance/SlasherUtil.sol +++ /dev/null @@ -1,100 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "../common/Initializable.sol"; -import "../common/UsingRegistry.sol"; -import "../common/UsingPrecompiles.sol"; -import "../common/interfaces/ICeloVersionedContract.sol"; - -contract SlasherUtil is Ownable, Initializable, UsingRegistry, UsingPrecompiles { - using SafeMath for uint256; - - struct SlashingIncentives { - // Value of LockedGold to slash from the account. - uint256 penalty; - // Value of LockedGold to send to the observer. - uint256 reward; - } - - SlashingIncentives public slashingIncentives; - - event SlashingIncentivesSet(uint256 penalty, uint256 reward); - - /** - * @notice Sets initialized == true on implementation contracts - * @param test Set to true to skip implementation initialization - */ - constructor(bool test) public Initializable(test) {} - - /** - * @notice Sets slashing incentives. - * @param penalty Penalty for the slashed signer. - * @param reward Reward that the observer gets. - */ - function setSlashingIncentives(uint256 penalty, uint256 reward) public onlyOwner { - require(penalty > reward, "Penalty has to be larger than reward"); - slashingIncentives.penalty = penalty; - slashingIncentives.reward = reward; - emit SlashingIncentivesSet(penalty, reward); - } - - /** - * @notice Returns the group to be slashed. - * @param validator Validator that was slashed. - * @param blockNumber Block number associated with slashing. - * @param groupMembershipHistoryIndex Index used for history lookup. - * @return Group to be slashed. - */ - function groupMembershipAtBlock( - address validator, - uint256 blockNumber, - uint256 groupMembershipHistoryIndex - ) public view returns (address) { - uint256 epoch = getEpochNumberOfBlock(blockNumber); - require(epoch != 0, "Cannot slash on epoch 0"); - // Use `epoch-1` because the elections were on that epoch - return - getValidators().groupMembershipInEpoch(validator, epoch.sub(1), groupMembershipHistoryIndex); - } - - function performSlashing( - address validator, - address recipient, - uint256 startBlock, - uint256 groupMembershipHistoryIndex, - address[] memory validatorElectionLessers, - address[] memory validatorElectionGreaters, - uint256[] memory validatorElectionIndices, - address[] memory groupElectionLessers, - address[] memory groupElectionGreaters, - uint256[] memory groupElectionIndices - ) internal { - ILockedGold lockedGold = getLockedGold(); - lockedGold.slash( - validator, - slashingIncentives.penalty, - recipient, - slashingIncentives.reward, - validatorElectionLessers, - validatorElectionGreaters, - validatorElectionIndices - ); - address group = groupMembershipAtBlock(validator, startBlock, groupMembershipHistoryIndex); - assert(group != address(0)); - lockedGold.slash( - group, - slashingIncentives.penalty, - recipient, - slashingIncentives.reward, - groupElectionLessers, - groupElectionGreaters, - groupElectionIndices - ); - IValidators validators = getValidators(); - validators.forceDeaffiliateIfValidator(validator); - validators.halveSlashingMultiplier(group); - } - -} diff --git a/packages/protocol/contracts/governance/Validators.sol b/packages/protocol/contracts/governance/Validators.sol deleted file mode 100644 index 39e007fff..000000000 --- a/packages/protocol/contracts/governance/Validators.sol +++ /dev/null @@ -1,1401 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/Math.sol"; -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; -import "solidity-bytes-utils/contracts/BytesLib.sol"; - -import "./interfaces/IValidators.sol"; - -import "../common/CalledByVm.sol"; -import "../common/Initializable.sol"; -import "../common/FixidityLib.sol"; -import "../common/linkedlists/AddressLinkedList.sol"; -import "../common/UsingRegistry.sol"; -import "../common/UsingPrecompiles.sol"; -import "../common/interfaces/ICeloVersionedContract.sol"; -import "../common/libraries/ReentrancyGuard.sol"; - -/** - * @title A contract for registering and electing Validator Groups and Validators. - */ -contract Validators is - IValidators, - ICeloVersionedContract, - Ownable, - ReentrancyGuard, - Initializable, - UsingRegistry, - UsingPrecompiles, - CalledByVm -{ - using FixidityLib for FixidityLib.Fraction; - using AddressLinkedList for LinkedList.List; - using SafeMath for uint256; - using BytesLib for bytes; - - // For Validators, these requirements must be met in order to: - // 1. Register a validator - // 2. Affiliate with and be added to a group - // 3. Receive epoch payments (note that the group must meet the group requirements as well) - // Accounts may de-register their Validator `duration` seconds after they were last a member of a - // group, after which no restrictions on Locked Gold will apply to the account. - // - // For Validator Groups, these requirements must be met in order to: - // 1. Register a group - // 2. Add a member to a group - // 3. Receive epoch payments - // Note that for groups, the requirement value is multiplied by the number of members, and is - // enforced for `duration` seconds after the group last had that number of members. - // Accounts may de-register their Group `duration` seconds after they were last non-empty, after - // which no restrictions on Locked Gold will apply to the account. - struct LockedGoldRequirements { - uint256 value; - // In seconds. - uint256 duration; - } - - struct ValidatorGroup { - bool exists; - LinkedList.List members; - FixidityLib.Fraction commission; - FixidityLib.Fraction nextCommission; - uint256 nextCommissionBlock; - // sizeHistory[i] contains the last time the group contained i members. - uint256[] sizeHistory; - SlashingInfo slashInfo; - } - - // Stores the epoch number at which a validator joined a particular group. - struct MembershipHistoryEntry { - uint256 epochNumber; - address group; - } - - // Stores the per-epoch membership history of a validator, used to determine which group - // commission should be paid to at the end of an epoch. - // Stores a timestamp of the last time the validator was removed from a group, used to determine - // whether or not a group can de-register. - struct MembershipHistory { - // The key to the most recent entry in the entries mapping. - uint256 tail; - // The number of entries in this validators membership history. - uint256 numEntries; - mapping(uint256 => MembershipHistoryEntry) entries; - uint256 lastRemovedFromGroupTimestamp; - } - - struct SlashingInfo { - FixidityLib.Fraction multiplier; - uint256 lastSlashed; - } - - struct PublicKeys { - bytes ecdsa; - bytes bls; - } - - struct Validator { - PublicKeys publicKeys; - address affiliation; - FixidityLib.Fraction score; - MembershipHistory membershipHistory; - } - - // Parameters that govern the calculation of validator's score. - struct ValidatorScoreParameters { - uint256 exponent; - FixidityLib.Fraction adjustmentSpeed; - } - - mapping(address => ValidatorGroup) private groups; - mapping(address => Validator) private validators; - address[] private registeredGroups; - address[] private registeredValidators; - LockedGoldRequirements public validatorLockedGoldRequirements; - LockedGoldRequirements public groupLockedGoldRequirements; - ValidatorScoreParameters private validatorScoreParameters; - uint256 public membershipHistoryLength; - uint256 public maxGroupSize; - // The number of blocks to delay a ValidatorGroup's commission update - uint256 public commissionUpdateDelay; - uint256 public slashingMultiplierResetPeriod; - uint256 public downtimeGracePeriod; - - event MaxGroupSizeSet(uint256 size); - event CommissionUpdateDelaySet(uint256 delay); - event ValidatorScoreParametersSet(uint256 exponent, uint256 adjustmentSpeed); - event GroupLockedGoldRequirementsSet(uint256 value, uint256 duration); - event ValidatorLockedGoldRequirementsSet(uint256 value, uint256 duration); - event MembershipHistoryLengthSet(uint256 length); - event ValidatorRegistered(address indexed validator); - event ValidatorDeregistered(address indexed validator); - event ValidatorAffiliated(address indexed validator, address indexed group); - event ValidatorDeaffiliated(address indexed validator, address indexed group); - event ValidatorEcdsaPublicKeyUpdated(address indexed validator, bytes ecdsaPublicKey); - event ValidatorBlsPublicKeyUpdated(address indexed validator, bytes blsPublicKey); - event ValidatorScoreUpdated(address indexed validator, uint256 score, uint256 epochScore); - event ValidatorGroupRegistered(address indexed group, uint256 commission); - event ValidatorGroupDeregistered(address indexed group); - event ValidatorGroupMemberAdded(address indexed group, address indexed validator); - event ValidatorGroupMemberRemoved(address indexed group, address indexed validator); - event ValidatorGroupMemberReordered(address indexed group, address indexed validator); - event ValidatorGroupCommissionUpdateQueued( - address indexed group, - uint256 commission, - uint256 activationBlock - ); - event ValidatorGroupCommissionUpdated(address indexed group, uint256 commission); - event ValidatorEpochPaymentDistributed( - address indexed validator, - uint256 validatorPayment, - address indexed group, - uint256 groupPayment - ); - - modifier onlySlasher() { - require(getLockedGold().isSlasher(msg.sender), "Only registered slasher can call"); - _; - } - - /** - * @notice Returns the storage, major, minor, and patch version of the contract. - * @return Storage version of the contract. - * @return Major version of the contract. - * @return Minor version of the contract. - * @return Patch version of the contract. - */ - function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { - return (1, 2, 0, 5); - } - - /** - * @notice Sets initialized == true on implementation contracts - * @param test Set to true to skip implementation initialization - */ - constructor(bool test) public Initializable(test) {} - - /** - * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. - * @param registryAddress The address of the registry core smart contract. - * @param groupRequirementValue The Locked Gold requirement amount for groups. - * @param groupRequirementDuration The Locked Gold requirement duration for groups. - * @param validatorRequirementValue The Locked Gold requirement amount for validators. - * @param validatorRequirementDuration The Locked Gold requirement duration for validators. - * @param validatorScoreExponent The exponent used in calculating validator scores. - * @param validatorScoreAdjustmentSpeed The speed at which validator scores are adjusted. - * @param _membershipHistoryLength The max number of entries for validator membership history. - * @param _maxGroupSize The maximum group size. - * @param _commissionUpdateDelay The number of blocks to delay a ValidatorGroup's commission - * update. - * @dev Should be called only once. - */ - function initialize( - address registryAddress, - uint256 groupRequirementValue, - uint256 groupRequirementDuration, - uint256 validatorRequirementValue, - uint256 validatorRequirementDuration, - uint256 validatorScoreExponent, - uint256 validatorScoreAdjustmentSpeed, - uint256 _membershipHistoryLength, - uint256 _slashingMultiplierResetPeriod, - uint256 _maxGroupSize, - uint256 _commissionUpdateDelay, - uint256 _downtimeGracePeriod - ) external initializer { - _transferOwnership(msg.sender); - setRegistry(registryAddress); - setGroupLockedGoldRequirements(groupRequirementValue, groupRequirementDuration); - setValidatorLockedGoldRequirements(validatorRequirementValue, validatorRequirementDuration); - setValidatorScoreParameters(validatorScoreExponent, validatorScoreAdjustmentSpeed); - setMaxGroupSize(_maxGroupSize); - setCommissionUpdateDelay(_commissionUpdateDelay); - setMembershipHistoryLength(_membershipHistoryLength); - setSlashingMultiplierResetPeriod(_slashingMultiplierResetPeriod); - setDowntimeGracePeriod(_downtimeGracePeriod); - } - - /** - * @notice Updates the block delay for a ValidatorGroup's commission udpdate - * @param delay Number of blocks to delay the update - */ - function setCommissionUpdateDelay(uint256 delay) public onlyOwner { - require(delay != commissionUpdateDelay, "commission update delay not changed"); - commissionUpdateDelay = delay; - emit CommissionUpdateDelaySet(delay); - } - - /** - * @notice Updates the maximum number of members a group can have. - * @param size The maximum group size. - * @return True upon success. - */ - function setMaxGroupSize(uint256 size) public onlyOwner returns (bool) { - require(0 < size, "Max group size cannot be zero"); - require(size != maxGroupSize, "Max group size not changed"); - maxGroupSize = size; - emit MaxGroupSizeSet(size); - return true; - } - - /** - * @notice Updates the number of validator group membership entries to store. - * @param length The number of validator group membership entries to store. - * @return True upon success. - */ - function setMembershipHistoryLength(uint256 length) public onlyOwner returns (bool) { - require(0 < length, "Membership history length cannot be zero"); - require(length != membershipHistoryLength, "Membership history length not changed"); - membershipHistoryLength = length; - emit MembershipHistoryLengthSet(length); - return true; - } - - /** - * @notice Updates the validator score parameters. - * @param exponent The exponent used in calculating the score. - * @param adjustmentSpeed The speed at which the score is adjusted. - * @return True upon success. - */ - function setValidatorScoreParameters(uint256 exponent, uint256 adjustmentSpeed) - public - onlyOwner - returns (bool) - { - require( - adjustmentSpeed <= FixidityLib.fixed1().unwrap(), - "Adjustment speed cannot be larger than 1" - ); - require( - exponent != validatorScoreParameters.exponent || - !FixidityLib.wrap(adjustmentSpeed).equals(validatorScoreParameters.adjustmentSpeed), - "Adjustment speed and exponent not changed" - ); - validatorScoreParameters = ValidatorScoreParameters( - exponent, - FixidityLib.wrap(adjustmentSpeed) - ); - emit ValidatorScoreParametersSet(exponent, adjustmentSpeed); - return true; - } - - /** - * @notice Returns the maximum number of members a group can add. - * @return The maximum number of members a group can add. - */ - function getMaxGroupSize() external view returns (uint256) { - return maxGroupSize; - } - - /** - * @notice Returns the block delay for a ValidatorGroup's commission udpdate. - * @return The block delay for a ValidatorGroup's commission udpdate. - */ - function getCommissionUpdateDelay() external view returns (uint256) { - return commissionUpdateDelay; - } - - /** - * @notice Updates the Locked Gold requirements for Validator Groups. - * @param value The per-member amount of Locked Gold required. - * @param duration The time (in seconds) that these requirements persist for. - * @return True upon success. - */ - function setGroupLockedGoldRequirements(uint256 value, uint256 duration) - public - onlyOwner - returns (bool) - { - LockedGoldRequirements storage requirements = groupLockedGoldRequirements; - require( - value != requirements.value || duration != requirements.duration, - "Group requirements not changed" - ); - groupLockedGoldRequirements = LockedGoldRequirements(value, duration); - emit GroupLockedGoldRequirementsSet(value, duration); - return true; - } - - /** - * @notice Updates the Locked Gold requirements for Validators. - * @param value The amount of Locked Gold required. - * @param duration The time (in seconds) that these requirements persist for. - * @return True upon success. - */ - function setValidatorLockedGoldRequirements(uint256 value, uint256 duration) - public - onlyOwner - returns (bool) - { - LockedGoldRequirements storage requirements = validatorLockedGoldRequirements; - require( - value != requirements.value || duration != requirements.duration, - "Validator requirements not changed" - ); - validatorLockedGoldRequirements = LockedGoldRequirements(value, duration); - emit ValidatorLockedGoldRequirementsSet(value, duration); - return true; - } - - /** - * @notice Registers a validator unaffiliated with any validator group. - * @param ecdsaPublicKey The ECDSA public key that the validator is using for consensus, should - * match the validator signer. 64 bytes. - * @param blsPublicKey The BLS public key that the validator is using for consensus, should pass - * proof of possession. 96 bytes. - * @param blsPop The BLS public key proof-of-possession, which consists of a signature on the - * account address. 48 bytes. - * @return True upon success. - * @dev Fails if the account is already a validator or validator group. - * @dev Fails if the account does not have sufficient Locked Gold. - */ - function registerValidator( - bytes calldata ecdsaPublicKey, - bytes calldata blsPublicKey, - bytes calldata blsPop - ) external nonReentrant returns (bool) { - address account = getAccounts().validatorSignerToAccount(msg.sender); - _isRegistrationAllowed(account); - require(!isValidator(account) && !isValidatorGroup(account), "Already registered"); - uint256 lockedGoldBalance = getLockedGold().getAccountTotalLockedGold(account); - require(lockedGoldBalance >= validatorLockedGoldRequirements.value, "Deposit too small"); - Validator storage validator = validators[account]; - address signer = getAccounts().getValidatorSigner(account); - require( - _updateEcdsaPublicKey(validator, account, signer, ecdsaPublicKey), - "Error updating ECDSA public key" - ); - require( - _updateBlsPublicKey(validator, account, blsPublicKey, blsPop), - "Error updating BLS public key" - ); - registeredValidators.push(account); - updateMembershipHistory(account, address(0)); - emit ValidatorRegistered(account); - return true; - } - - /** - * @notice Returns the parameters that govern how a validator's score is calculated. - * @return The exponent that governs how a validator's score is calculated. - * @return The adjustment speed that governs how a validator's score is calculated. - */ - function getValidatorScoreParameters() external view returns (uint256, uint256) { - return (validatorScoreParameters.exponent, validatorScoreParameters.adjustmentSpeed.unwrap()); - } - - /** - * @notice Returns the group membership history of a validator. - * @param account The validator whose membership history to return. - * @return epochs The epochs of a validator. - * @return The membership groups of a validator. - * @return The last removed from group timestamp of a validator. - * @return The tail of a validator. - */ - function getMembershipHistory(address account) - external - view - returns (uint256[] memory, address[] memory, uint256, uint256) - { - MembershipHistory storage history = validators[account].membershipHistory; - uint256[] memory epochs = new uint256[](history.numEntries); - address[] memory membershipGroups = new address[](history.numEntries); - for (uint256 i = 0; i < history.numEntries; i = i.add(1)) { - uint256 index = history.tail.add(i); - epochs[i] = history.entries[index].epochNumber; - membershipGroups[i] = history.entries[index].group; - } - return (epochs, membershipGroups, history.lastRemovedFromGroupTimestamp, history.tail); - } - - /** - * @notice Calculates the validator score for an epoch from the uptime value for the epoch. - * @param uptime The Fixidity representation of the validator's uptime, between 0 and 1. - * @dev epoch_score = uptime ** exponent - * @return Fixidity representation of the epoch score between 0 and 1. - */ - function calculateEpochScore(uint256 uptime) public view returns (uint256) { - require(uptime <= FixidityLib.fixed1().unwrap(), "Uptime cannot be larger than one"); - uint256 numerator; - uint256 denominator; - uptime = Math.min(uptime.add(downtimeGracePeriod), FixidityLib.fixed1().unwrap()); - (numerator, denominator) = fractionMulExp( - FixidityLib.fixed1().unwrap(), - FixidityLib.fixed1().unwrap(), - uptime, - FixidityLib.fixed1().unwrap(), - validatorScoreParameters.exponent, - 18 - ); - return FixidityLib.newFixedFraction(numerator, denominator).unwrap(); - } - - /** - * @notice Calculates the aggregate score of a group for an epoch from individual uptimes. - * @param uptimes Array of Fixidity representations of the validators' uptimes, between 0 and 1. - * @dev group_score = average(uptimes ** exponent) - * @return Fixidity representation of the group epoch score between 0 and 1. - */ - function calculateGroupEpochScore(uint256[] calldata uptimes) external view returns (uint256) { - require(uptimes.length > 0, "Uptime array empty"); - require(uptimes.length <= maxGroupSize, "Uptime array larger than maximum group size"); - FixidityLib.Fraction memory sum; - for (uint256 i = 0; i < uptimes.length; i = i.add(1)) { - sum = sum.add(FixidityLib.wrap(calculateEpochScore(uptimes[i]))); - } - return sum.divide(FixidityLib.newFixed(uptimes.length)).unwrap(); - } - - /** - * @notice Updates a validator's score based on its uptime for the epoch. - * @param signer The validator signer of the validator account whose score needs updating. - * @param uptime The Fixidity representation of the validator's uptime, between 0 and 1. - * @return True upon success. - */ - function updateValidatorScoreFromSigner(address signer, uint256 uptime) external onlyVm() { - _updateValidatorScoreFromSigner(signer, uptime); - } - - /** - * @notice Updates a validator's score based on its uptime for the epoch. - * @param signer The validator signer of the validator whose score needs updating. - * @param uptime The Fixidity representation of the validator's uptime, between 0 and 1. - * @dev new_score = uptime ** exponent * adjustmentSpeed + old_score * (1 - adjustmentSpeed) - * @return True upon success. - */ - function _updateValidatorScoreFromSigner(address signer, uint256 uptime) internal { - address account = getAccounts().signerToAccount(signer); - require(isValidator(account), "Not a validator"); - - FixidityLib.Fraction memory epochScore = FixidityLib.wrap(calculateEpochScore(uptime)); - FixidityLib.Fraction memory newComponent = validatorScoreParameters.adjustmentSpeed.multiply( - epochScore - ); - - FixidityLib.Fraction memory currentComponent = FixidityLib.fixed1().subtract( - validatorScoreParameters.adjustmentSpeed - ); - currentComponent = currentComponent.multiply(validators[account].score); - validators[account].score = FixidityLib.wrap( - Math.min(epochScore.unwrap(), newComponent.add(currentComponent).unwrap()) - ); - emit ValidatorScoreUpdated(account, validators[account].score.unwrap(), epochScore.unwrap()); - } - - /** - * @notice Distributes epoch payments to the account associated with `signer` and its group. - * @param signer The validator signer of the account to distribute the epoch payment to. - * @param maxPayment The maximum payment to the validator. Actual payment is based on score and - * group commission. - * @return The total payment paid to the validator and their group. - */ - function distributeEpochPaymentsFromSigner(address signer, uint256 maxPayment) - external - onlyVm() - returns (uint256) - { - return _distributeEpochPaymentsFromSigner(signer, maxPayment); - } - - /** - * @notice Distributes epoch payments to the account associated with `signer` and its group. - * @param signer The validator signer of the validator to distribute the epoch payment to. - * @param maxPayment The maximum payment to the validator. Actual payment is based on score and - * group commission. - * @return The total payment paid to the validator and their group. - */ - function _distributeEpochPaymentsFromSigner(address signer, uint256 maxPayment) - internal - returns (uint256) - { - address account = getAccounts().signerToAccount(signer); - require(isValidator(account), "Not a validator"); - // The group that should be paid is the group that the validator was a member of at the - // time it was elected. - address group = getMembershipInLastEpoch(account); - require(group != address(0), "Validator not registered with a group"); - // Both the validator and the group must maintain the minimum locked gold balance in order to - // receive epoch payments. - if (meetsAccountLockedGoldRequirements(account) && meetsAccountLockedGoldRequirements(group)) { - FixidityLib.Fraction memory totalPayment = FixidityLib - .newFixed(maxPayment) - .multiply(validators[account].score) - .multiply(groups[group].slashInfo.multiplier); - uint256 groupPayment = totalPayment.multiply(groups[group].commission).fromFixed(); - FixidityLib.Fraction memory remainingPayment = FixidityLib.newFixed( - totalPayment.fromFixed().sub(groupPayment) - ); - (address beneficiary, uint256 fraction) = getAccounts().getPaymentDelegation(account); - uint256 delegatedPayment = remainingPayment.multiply(FixidityLib.wrap(fraction)).fromFixed(); - uint256 validatorPayment = remainingPayment.fromFixed().sub(delegatedPayment); - IStableToken stableToken = getStableToken(); - require(stableToken.mint(group, groupPayment), "mint failed to validator group"); - require(stableToken.mint(account, validatorPayment), "mint failed to validator account"); - if (fraction != 0) { - require(stableToken.mint(beneficiary, delegatedPayment), "mint failed to delegatee"); - } - emit ValidatorEpochPaymentDistributed(account, validatorPayment, group, groupPayment); - return totalPayment.fromFixed(); - } else { - return 0; - } - } - - /** - * @notice De-registers a validator. - * @param index The index of this validator in the list of all registered validators. - * @return True upon success. - * @dev Fails if the account is not a validator. - * @dev Fails if the validator has been a member of a group too recently. - */ - function deregisterValidator(uint256 index) external nonReentrant returns (bool) { - address account = getAccounts().validatorSignerToAccount(msg.sender); - require(isValidator(account), "Not a validator"); - - // Require that the validator has not been a member of a validator group for - // `validatorLockedGoldRequirements.duration` seconds. - Validator storage validator = validators[account]; - if (validator.affiliation != address(0)) { - require( - !groups[validator.affiliation].members.contains(account), - "Has been group member recently" - ); - } - uint256 requirementEndTime = validator.membershipHistory.lastRemovedFromGroupTimestamp.add( - validatorLockedGoldRequirements.duration - ); - require(requirementEndTime < now, "Not yet requirement end time"); - - // Remove the validator. - deleteElement(registeredValidators, account, index); - delete validators[account]; - emit ValidatorDeregistered(account); - return true; - } - - /** - * @notice Affiliates a validator with a group, allowing it to be added as a member. - * @param group The validator group with which to affiliate. - * @return True upon success. - * @dev De-affiliates with the previously affiliated group if present. - */ - function affiliate(address group) external nonReentrant returns (bool) { - address account = getAccounts().validatorSignerToAccount(msg.sender); - require(isValidator(account), "Not a validator"); - require(isValidatorGroup(group), "Not a validator group"); - require(meetsAccountLockedGoldRequirements(account), "Validator doesn't meet requirements"); - require(meetsAccountLockedGoldRequirements(group), "Group doesn't meet requirements"); - Validator storage validator = validators[account]; - if (validator.affiliation != address(0)) { - _deaffiliate(validator, account); - } - validator.affiliation = group; - emit ValidatorAffiliated(account, group); - return true; - } - - /** - * @notice De-affiliates a validator, removing it from the group for which it is a member. - * @return True upon success. - * @dev Fails if the account is not a validator with non-zero affiliation. - */ - function deaffiliate() external nonReentrant returns (bool) { - address account = getAccounts().validatorSignerToAccount(msg.sender); - require(isValidator(account), "Not a validator"); - Validator storage validator = validators[account]; - require(validator.affiliation != address(0), "deaffiliate: not affiliated"); - _deaffiliate(validator, account); - return true; - } - - /** - * @notice Updates a validator's BLS key. - * @param blsPublicKey The BLS public key that the validator is using for consensus, should pass - * proof of possession. 48 bytes. - * @param blsPop The BLS public key proof-of-possession, which consists of a signature on the - * account address. 48 bytes. - * @return True upon success. - */ - function updateBlsPublicKey(bytes calldata blsPublicKey, bytes calldata blsPop) - external - returns (bool) - { - address account = getAccounts().validatorSignerToAccount(msg.sender); - require(isValidator(account), "Not a validator"); - Validator storage validator = validators[account]; - require( - _updateBlsPublicKey(validator, account, blsPublicKey, blsPop), - "Error updating BLS public key" - ); - return true; - } - - /** - * @notice Updates a validator's BLS key. - * @param validator The validator whose BLS public key should be updated. - * @param account The address under which the validator is registered. - * @param blsPublicKey The BLS public key that the validator is using for consensus, should pass - * proof of possession. 96 bytes. - * @param blsPop The BLS public key proof-of-possession, which consists of a signature on the - * account address. 48 bytes. - * @return True upon success. - */ - function _updateBlsPublicKey( - Validator storage validator, - address account, - bytes memory blsPublicKey, - bytes memory blsPop - ) private returns (bool) { - require(blsPublicKey.length == 96, "Wrong BLS public key length"); - require(blsPop.length == 48, "Wrong BLS PoP length"); - require(checkProofOfPossession(account, blsPublicKey, blsPop), "Invalid BLS PoP"); - validator.publicKeys.bls = blsPublicKey; - emit ValidatorBlsPublicKeyUpdated(account, blsPublicKey); - return true; - } - - /** - * @notice Updates a validator's ECDSA key. - * @param account The address under which the validator is registered. - * @param signer The address which the validator is using to sign consensus messages. - * @param ecdsaPublicKey The ECDSA public key corresponding to `signer`. - * @return True upon success. - */ - function updateEcdsaPublicKey(address account, address signer, bytes calldata ecdsaPublicKey) - external - onlyRegisteredContract(ACCOUNTS_REGISTRY_ID) - returns (bool) - { - require(isValidator(account), "Not a validator"); - Validator storage validator = validators[account]; - require( - _updateEcdsaPublicKey(validator, account, signer, ecdsaPublicKey), - "Error updating ECDSA public key" - ); - return true; - } - - /** - * @notice Updates a validator's ECDSA key. - * @param validator The validator whose ECDSA public key should be updated. - * @param signer The address with which the validator is signing consensus messages. - * @param ecdsaPublicKey The ECDSA public key that the validator is using for consensus. Should - * match `signer`. 64 bytes. - * @return True upon success. - */ - function _updateEcdsaPublicKey( - Validator storage validator, - address account, - address signer, - bytes memory ecdsaPublicKey - ) private returns (bool) { - require(ecdsaPublicKey.length == 64, "Wrong ECDSA public key length"); - require( - address(uint160(uint256(keccak256(ecdsaPublicKey)))) == signer, - "ECDSA key does not match signer" - ); - validator.publicKeys.ecdsa = ecdsaPublicKey; - emit ValidatorEcdsaPublicKeyUpdated(account, ecdsaPublicKey); - return true; - } - - /** - * @notice Updates a validator's ECDSA and BLS keys. - * @param account The address under which the validator is registered. - * @param signer The address which the validator is using to sign consensus messages. - * @param ecdsaPublicKey The ECDSA public key corresponding to `signer`. - * @param blsPublicKey The BLS public key that the validator is using for consensus, should pass - * proof of possession. 96 bytes. - * @param blsPop The BLS public key proof-of-possession, which consists of a signature on the - * account address. 48 bytes. - * @return True upon success. - */ - function updatePublicKeys( - address account, - address signer, - bytes calldata ecdsaPublicKey, - bytes calldata blsPublicKey, - bytes calldata blsPop - ) external onlyRegisteredContract(ACCOUNTS_REGISTRY_ID) returns (bool) { - require(isValidator(account), "Not a validator"); - Validator storage validator = validators[account]; - require( - _updateEcdsaPublicKey(validator, account, signer, ecdsaPublicKey), - "Error updating ECDSA public key" - ); - require( - _updateBlsPublicKey(validator, account, blsPublicKey, blsPop), - "Error updating BLS public key" - ); - return true; - } - - /** - * @notice Registers a validator group with no member validators. - * @param commission Fixidity representation of the commission this group receives on epoch - * payments made to its members. - * @return True upon success. - * @dev Fails if the account is already a validator or validator group. - * @dev Fails if the account does not have sufficient weight. - */ - function registerValidatorGroup(uint256 commission) external nonReentrant returns (bool) { - require(commission <= FixidityLib.fixed1().unwrap(), "Commission can't be greater than 100%"); - address account = getAccounts().validatorSignerToAccount(msg.sender); - _isRegistrationAllowed(account); - require(!isValidator(account), "Already registered as validator"); - require(!isValidatorGroup(account), "Already registered as group"); - uint256 lockedGoldBalance = getLockedGold().getAccountTotalLockedGold(account); - require(lockedGoldBalance >= groupLockedGoldRequirements.value, "Not enough locked gold"); - ValidatorGroup storage group = groups[account]; - group.exists = true; - group.commission = FixidityLib.wrap(commission); - group.slashInfo = SlashingInfo(FixidityLib.fixed1(), 0); - registeredGroups.push(account); - emit ValidatorGroupRegistered(account, commission); - return true; - } - - function _isRegistrationAllowed(address account) private returns (bool) { - require( - !getElection().allowedToVoteOverMaxNumberOfGroups(account), - "Cannot vote for more than max number of groups" - ); - require( - // Validator could avoid getting slashed by delegating Celo to delegatees that would be voting - // for lots of proposals. Such transaction could run out of gas. - getLockedGold().getAccountTotalDelegatedFraction(account) == 0, - "Cannot delegate governance power" - ); - } - - /** - * @notice De-registers a validator group. - * @param index The index of this validator group in the list of all validator groups. - * @return True upon success. - * @dev Fails if the account is not a validator group with no members. - * @dev Fails if the group has had members too recently. - */ - function deregisterValidatorGroup(uint256 index) external nonReentrant returns (bool) { - address account = getAccounts().validatorSignerToAccount(msg.sender); - // Only Validator Groups that have never had members or have been empty for at least - // `groupLockedGoldRequirements.duration` seconds can be deregistered. - require(isValidatorGroup(account), "Not a validator group"); - require(groups[account].members.numElements == 0, "Validator group not empty"); - uint256[] storage sizeHistory = groups[account].sizeHistory; - if (sizeHistory.length > 1) { - require( - sizeHistory[1].add(groupLockedGoldRequirements.duration) < now, - "Hasn't been empty for long enough" - ); - } - delete groups[account]; - deleteElement(registeredGroups, account, index); - emit ValidatorGroupDeregistered(account); - return true; - } - - /** - * @notice Adds a member to the end of a validator group's list of members. - * @param validator The validator to add to the group - * @return True upon success. - * @dev Fails if `validator` has not set their affiliation to this account. - * @dev Fails if the group has zero members. - */ - function addMember(address validator) external nonReentrant returns (bool) { - address account = getAccounts().validatorSignerToAccount(msg.sender); - require(groups[account].members.numElements > 0, "Validator group empty"); - return _addMember(account, validator, address(0), address(0)); - } - - /** - * @notice Adds the first member to a group's list of members and marks it eligible for election. - * @param validator The validator to add to the group - * @param lesser The address of the group that has received fewer votes than this group. - * @param greater The address of the group that has received more votes than this group. - * @return True upon success. - * @dev Fails if `validator` has not set their affiliation to this account. - * @dev Fails if the group has > 0 members. - */ - function addFirstMember(address validator, address lesser, address greater) - external - nonReentrant - returns (bool) - { - address account = getAccounts().validatorSignerToAccount(msg.sender); - require(groups[account].members.numElements == 0, "Validator group not empty"); - return _addMember(account, validator, lesser, greater); - } - - /** - * @notice Adds a member to the end of a validator group's list of members. - * @param group The address of the validator group. - * @param validator The validator to add to the group. - * @param lesser The address of the group that has received fewer votes than this group. - * @param greater The address of the group that has received more votes than this group. - * @return True upon success. - * @dev Fails if `validator` has not set their affiliation to this account. - * @dev Fails if the group has > 0 members. - */ - function _addMember(address group, address validator, address lesser, address greater) - private - returns (bool) - { - require(isValidatorGroup(group) && isValidator(validator), "Not validator and group"); - ValidatorGroup storage _group = groups[group]; - require(_group.members.numElements < maxGroupSize, "group would exceed maximum size"); - require(validators[validator].affiliation == group, "Not affiliated to group"); - require(!_group.members.contains(validator), "Already in group"); - uint256 numMembers = _group.members.numElements.add(1); - _group.members.push(validator); - require(meetsAccountLockedGoldRequirements(group), "Group requirements not met"); - require(meetsAccountLockedGoldRequirements(validator), "Validator requirements not met"); - if (numMembers == 1) { - getElection().markGroupEligible(group, lesser, greater); - } - updateMembershipHistory(validator, group); - updateSizeHistory(group, numMembers.sub(1)); - emit ValidatorGroupMemberAdded(group, validator); - return true; - } - - /** - * @notice Removes a member from a validator group. - * @param validator The validator to remove from the group - * @return True upon success. - * @dev Fails if `validator` is not a member of the account's group. - */ - function removeMember(address validator) external nonReentrant returns (bool) { - address account = getAccounts().validatorSignerToAccount(msg.sender); - require(isValidatorGroup(account) && isValidator(validator), "is not group and validator"); - return _removeMember(account, validator); - } - - /** - * @notice Reorders a member within a validator group. - * @param validator The validator to reorder. - * @param lesserMember The member who will be behind `validator`, or 0 if `validator` will be the - * last member. - * @param greaterMember The member who will be ahead of `validator`, or 0 if `validator` will be - * the first member. - * @return True upon success. - * @dev Fails if `validator` is not a member of the account's validator group. - */ - function reorderMember(address validator, address lesserMember, address greaterMember) - external - nonReentrant - returns (bool) - { - address account = getAccounts().validatorSignerToAccount(msg.sender); - require(isValidatorGroup(account), "Not a group"); - require(isValidator(validator), "Not a validator"); - ValidatorGroup storage group = groups[account]; - require(group.members.contains(validator), "Not a member of the group"); - group.members.update(validator, lesserMember, greaterMember); - emit ValidatorGroupMemberReordered(account, validator); - return true; - } - - /** - * @notice Queues an update to a validator group's commission. - * If there was a previously scheduled update, that is overwritten. - * @param commission Fixidity representation of the commission this group receives on epoch - * payments made to its members. Must be in the range [0, 1.0]. - */ - function setNextCommissionUpdate(uint256 commission) external { - address account = getAccounts().validatorSignerToAccount(msg.sender); - require(isValidatorGroup(account), "Not a validator group"); - ValidatorGroup storage group = groups[account]; - require(commission <= FixidityLib.fixed1().unwrap(), "Commission can't be greater than 100%"); - require(commission != group.commission.unwrap(), "Commission must be different"); - - group.nextCommission = FixidityLib.wrap(commission); - group.nextCommissionBlock = block.number.add(commissionUpdateDelay); - emit ValidatorGroupCommissionUpdateQueued(account, commission, group.nextCommissionBlock); - } - /** - * @notice Updates a validator group's commission based on the previously queued update - */ - function updateCommission() external { - address account = getAccounts().validatorSignerToAccount(msg.sender); - require(isValidatorGroup(account), "Not a validator group"); - ValidatorGroup storage group = groups[account]; - - require(group.nextCommissionBlock != 0, "No commission update queued"); - require(group.nextCommissionBlock <= block.number, "Can't apply commission update yet"); - - group.commission = group.nextCommission; - delete group.nextCommission; - delete group.nextCommissionBlock; - emit ValidatorGroupCommissionUpdated(account, group.commission.unwrap()); - } - - /** - * @notice Returns the current locked gold balance requirement for the supplied account. - * @param account The account that may have to meet locked gold balance requirements. - * @return The current locked gold balance requirement for the supplied account. - */ - function getAccountLockedGoldRequirement(address account) public view returns (uint256) { - if (isValidator(account)) { - return validatorLockedGoldRequirements.value; - } else if (isValidatorGroup(account)) { - uint256 multiplier = Math.max(1, groups[account].members.numElements); - uint256[] storage sizeHistory = groups[account].sizeHistory; - if (sizeHistory.length > 0) { - for (uint256 i = sizeHistory.length.sub(1); i > 0; i = i.sub(1)) { - if (sizeHistory[i].add(groupLockedGoldRequirements.duration) >= now) { - multiplier = Math.max(i, multiplier); - break; - } - } - } - return groupLockedGoldRequirements.value.mul(multiplier); - } - return 0; - } - - /** - * @notice Returns whether or not an account meets its Locked Gold requirements. - * @param account The address of the account. - * @return Whether or not an account meets its Locked Gold requirements. - */ - function meetsAccountLockedGoldRequirements(address account) public view returns (bool) { - uint256 balance = getLockedGold().getAccountTotalLockedGold(account); - // Add a bit of "wiggle room" to accommodate the fact that vote activation can result in ~1 - // wei rounding errors. Using 10 as an additional margin of safety. - return balance.add(10) >= getAccountLockedGoldRequirement(account); - } - - /** - * @notice Returns the validator BLS key. - * @param signer The account that registered the validator or its authorized signing address. - * @return The validator BLS key. - */ - function getValidatorBlsPublicKeyFromSigner(address signer) - external - view - returns (bytes memory blsPublicKey) - { - address account = getAccounts().signerToAccount(signer); - require(isValidator(account), "Not a validator"); - return validators[account].publicKeys.bls; - } - - /** - * @notice Returns validator information. - * @param account The account that registered the validator. - * @return The unpacked validator struct. - */ - function getValidator(address account) - public - view - returns ( - bytes memory ecdsaPublicKey, - bytes memory blsPublicKey, - address affiliation, - uint256 score, - address signer - ) - { - require(isValidator(account), "Not a validator"); - Validator storage validator = validators[account]; - return ( - validator.publicKeys.ecdsa, - validator.publicKeys.bls, - validator.affiliation, - validator.score.unwrap(), - getAccounts().getValidatorSigner(account) - ); - } - - /** - * @notice Returns validator group information. - * @param account The account that registered the validator group. - * @return keys The Keys. - * @return commision The commision. - * @return nextCommision The next commision. - * @return nextCommisionBlock The next commision block. - * @return size The Size history. - * @return multiplier The multiplier. - * @return lastSlashed The last slashed. - */ - function getValidatorGroup(address account) - external - view - returns (address[] memory, uint256, uint256, uint256, uint256[] memory, uint256, uint256) - { - require(isValidatorGroup(account), "Not a validator group"); - ValidatorGroup storage group = groups[account]; - return ( - group.members.getKeys(), - group.commission.unwrap(), - group.nextCommission.unwrap(), - group.nextCommissionBlock, - group.sizeHistory, - group.slashInfo.multiplier.unwrap(), - group.slashInfo.lastSlashed - ); - } - - /** - * @notice Returns the number of members in a validator group. - * @param account The address of the validator group. - * @return The number of members in a validator group. - */ - function getGroupNumMembers(address account) public view returns (uint256) { - require(isValidatorGroup(account), "Not validator group"); - return groups[account].members.numElements; - } - - /** - * @notice Returns the top n group members for a particular group. - * @param account The address of the validator group. - * @param n The number of members to return. - * @return The top n group members for a particular group. - */ - function getTopGroupValidators(address account, uint256 n) - external - view - returns (address[] memory) - { - address[] memory topAccounts = groups[account].members.headN(n); - address[] memory topValidators = new address[](n); - for (uint256 i = 0; i < n; i = i.add(1)) { - topValidators[i] = getAccounts().getValidatorSigner(topAccounts[i]); - } - return topValidators; - } - - /** - * @notice Returns the number of members in the provided validator groups. - * @param accounts The addresses of the validator groups. - * @return The number of members in the provided validator groups. - */ - function getGroupsNumMembers(address[] calldata accounts) - external - view - returns (uint256[] memory) - { - uint256[] memory numMembers = new uint256[](accounts.length); - for (uint256 i = 0; i < accounts.length; i = i.add(1)) { - numMembers[i] = getGroupNumMembers(accounts[i]); - } - return numMembers; - } - - /** - * @notice Returns the number of registered validators. - * @return The number of registered validators. - */ - function getNumRegisteredValidators() external view returns (uint256) { - return registeredValidators.length; - } - - /** - * @notice Returns the Locked Gold requirements for validators. - * @return The Locked Gold value. - * @return The Locked Gold duration. - */ - function getValidatorLockedGoldRequirements() external view returns (uint256, uint256) { - return (validatorLockedGoldRequirements.value, validatorLockedGoldRequirements.duration); - } - - /** - * @notice Returns the Locked Gold requirements for validator groups. - * @return The Locked Gold value. - * @return The Locked Gold duration. - */ - function getGroupLockedGoldRequirements() external view returns (uint256, uint256) { - return (groupLockedGoldRequirements.value, groupLockedGoldRequirements.duration); - } - - /** - * @notice Returns the list of registered validator accounts. - * @return The list of registered validator accounts. - */ - function getRegisteredValidators() external view returns (address[] memory) { - return registeredValidators; - } - - /** - * @notice Returns the list of signers for the registered validator accounts. - * @return The list of signers for registered validator accounts. - */ - function getRegisteredValidatorSigners() external view returns (address[] memory) { - IAccounts accounts = getAccounts(); - address[] memory signers = new address[](registeredValidators.length); - for (uint256 i = 0; i < signers.length; i = i.add(1)) { - signers[i] = accounts.getValidatorSigner(registeredValidators[i]); - } - return signers; - } - - /** - * @notice Returns the list of registered validator group accounts. - * @return The list of registered validator group addresses. - */ - function getRegisteredValidatorGroups() external view returns (address[] memory) { - return registeredGroups; - } - - /** - * @notice Returns whether a particular account has a registered validator group. - * @param account The account. - * @return Whether a particular address is a registered validator group. - */ - function isValidatorGroup(address account) public view returns (bool) { - return groups[account].exists; - } - - /** - * @notice Returns whether a particular account has a registered validator. - * @param account The account. - * @return Whether a particular address is a registered validator. - */ - function isValidator(address account) public view returns (bool) { - return validators[account].publicKeys.bls.length > 0; - } - - /** - * @notice Deletes an element from a list of addresses. - * @param list The list of addresses. - * @param element The address to delete. - * @param index The index of `element` in the list. - */ - function deleteElement(address[] storage list, address element, uint256 index) private { - require(index < list.length && list[index] == element, "deleteElement: index out of range"); - uint256 lastIndex = list.length.sub(1); - list[index] = list[lastIndex]; - delete list[lastIndex]; - list.length = lastIndex; - } - - /** - * @notice Removes a member from a validator group. - * @param group The group from which the member should be removed. - * @param validator The validator to remove from the group. - * @return True upon success. - * @dev If `validator` was the only member of `group`, `group` becomes unelectable. - * @dev Fails if `validator` is not a member of `group`. - */ - function _removeMember(address group, address validator) private returns (bool) { - ValidatorGroup storage _group = groups[group]; - require(validators[validator].affiliation == group, "Not affiliated to group"); - require(_group.members.contains(validator), "Not a member of the group"); - _group.members.remove(validator); - uint256 numMembers = _group.members.numElements; - // Empty validator groups are not electable. - if (numMembers == 0) { - getElection().markGroupIneligible(group); - } - updateMembershipHistory(validator, address(0)); - updateSizeHistory(group, numMembers.add(1)); - emit ValidatorGroupMemberRemoved(group, validator); - return true; - } - - /** - * @notice Updates the group membership history of a particular account. - * @param account The account whose group membership has changed. - * @param group The group that the account is now a member of. - * @return True upon success. - * @dev Note that this is used to determine a validator's membership at the time of an election, - * and so group changes within an epoch will overwrite eachother. - */ - function updateMembershipHistory(address account, address group) private returns (bool) { - MembershipHistory storage history = validators[account].membershipHistory; - uint256 epochNumber = getEpochNumber(); - uint256 head = history.numEntries == 0 ? 0 : history.tail.add(history.numEntries.sub(1)); - - if (history.numEntries > 0 && group == address(0)) { - history.lastRemovedFromGroupTimestamp = now; - } - - if (history.numEntries > 0 && history.entries[head].epochNumber == epochNumber) { - // There have been no elections since the validator last changed membership, overwrite the - // previous entry. - history.entries[head] = MembershipHistoryEntry(epochNumber, group); - return true; - } - - // There have been elections since the validator last changed membership, create a new entry. - uint256 index = history.numEntries == 0 ? 0 : head.add(1); - history.entries[index] = MembershipHistoryEntry(epochNumber, group); - if (history.numEntries < membershipHistoryLength) { - // Not enough entries, don't remove any. - history.numEntries = history.numEntries.add(1); - } else if (history.numEntries == membershipHistoryLength) { - // Exactly enough entries, delete the oldest one to account for the one we added. - delete history.entries[history.tail]; - history.tail = history.tail.add(1); - } else { - // Too many entries, delete the oldest two to account for the one we added. - delete history.entries[history.tail]; - delete history.entries[history.tail.add(1)]; - history.numEntries = history.numEntries.sub(1); - history.tail = history.tail.add(2); - } - return true; - } - - /** - * @notice Updates the size history of a validator group. - * @param group The account whose group size has changed. - * @param size The new size of the group. - * @dev Used to determine how much gold an account needs to keep locked. - */ - function updateSizeHistory(address group, uint256 size) private { - uint256[] storage sizeHistory = groups[group].sizeHistory; - if (size == sizeHistory.length) { - sizeHistory.push(now); - } else if (size < sizeHistory.length) { - sizeHistory[size] = now; - } else { - require(false, "Unable to update size history"); - } - } - - /** - * @notice Returns the group that `account` was a member of at the end of the last epoch. - * @param signer The signer of the account whose group membership should be returned. - * @return The group that `account` was a member of at the end of the last epoch. - */ - function getMembershipInLastEpochFromSigner(address signer) external view returns (address) { - address account = getAccounts().signerToAccount(signer); - require(isValidator(account), "Not a validator"); - return getMembershipInLastEpoch(account); - } - - /** - * @notice Returns the group that `account` was a member of at the end of the last epoch. - * @param account The account whose group membership should be returned. - * @return The group that `account` was a member of at the end of the last epoch. - */ - function getMembershipInLastEpoch(address account) public view returns (address) { - uint256 epochNumber = getEpochNumber(); - MembershipHistory storage history = validators[account].membershipHistory; - uint256 head = history.numEntries == 0 ? 0 : history.tail.add(history.numEntries.sub(1)); - // If the most recent entry in the membership history is for the current epoch number, we need - // to look at the previous entry. - if (history.entries[head].epochNumber == epochNumber) { - if (head > history.tail) { - head = head.sub(1); - } - } - return history.entries[head].group; - } - - /** - * @notice De-affiliates a validator, removing it from the group for which it is a member. - * @param validator The validator to deaffiliate from their affiliated validator group. - * @param validatorAccount The LockedGold account of the validator. - * @return True upon success. - */ - function _deaffiliate(Validator storage validator, address validatorAccount) - private - returns (bool) - { - address affiliation = validator.affiliation; - ValidatorGroup storage group = groups[affiliation]; - if (group.members.contains(validatorAccount)) { - _removeMember(affiliation, validatorAccount); - } - validator.affiliation = address(0); - emit ValidatorDeaffiliated(validatorAccount, affiliation); - return true; - } - - /** - * @notice Removes a validator from the group for which it is a member. - * @param validatorAccount The validator to deaffiliate from their affiliated validator group. - */ - function forceDeaffiliateIfValidator(address validatorAccount) external nonReentrant onlySlasher { - if (isValidator(validatorAccount)) { - Validator storage validator = validators[validatorAccount]; - if (validator.affiliation != address(0)) { - _deaffiliate(validator, validatorAccount); - } - } - } - - /** - * @notice Sets the slashingMultiplierRestPeriod property if called by owner. - * @param value New reset period for slashing multiplier. - */ - function setSlashingMultiplierResetPeriod(uint256 value) public nonReentrant onlyOwner { - slashingMultiplierResetPeriod = value; - } - - /** - * @notice Sets the downtimeGracePeriod property if called by owner. - * @param value New downtime grace period for calculating epoch scores. - */ - function setDowntimeGracePeriod(uint256 value) public nonReentrant onlyOwner { - downtimeGracePeriod = value; - } - - /** - * @notice Resets a group's slashing multiplier if it has been >= the reset period since - * the last time the group was slashed. - */ - function resetSlashingMultiplier() external nonReentrant { - address account = getAccounts().validatorSignerToAccount(msg.sender); - require(isValidatorGroup(account), "Not a validator group"); - ValidatorGroup storage group = groups[account]; - require( - now >= group.slashInfo.lastSlashed.add(slashingMultiplierResetPeriod), - "`resetSlashingMultiplier` called before resetPeriod expired" - ); - group.slashInfo.multiplier = FixidityLib.fixed1(); - } - - /** - * @notice Halves the group's slashing multiplier. - * @param account The group being slashed. - */ - function halveSlashingMultiplier(address account) external nonReentrant onlySlasher { - require(isValidatorGroup(account), "Not a validator group"); - ValidatorGroup storage group = groups[account]; - group.slashInfo.multiplier = FixidityLib.wrap(group.slashInfo.multiplier.unwrap().div(2)); - group.slashInfo.lastSlashed = now; - } - - /** - * @notice Getter for a group's slashing multiplier. - * @param account The group to fetch slashing multiplier for. - */ - function getValidatorGroupSlashingMultiplier(address account) external view returns (uint256) { - require(isValidatorGroup(account), "Not a validator group"); - ValidatorGroup storage group = groups[account]; - return group.slashInfo.multiplier.unwrap(); - } - - /** - * @notice Returns the group that `account` was a member of during `epochNumber`. - * @param account The account whose group membership should be returned. - * @param epochNumber The epoch number we are querying this account's membership at. - * @param index The index into the validator's history struct for their history at `epochNumber`. - * @return The group that `account` was a member of during `epochNumber`. - */ - function groupMembershipInEpoch(address account, uint256 epochNumber, uint256 index) - external - view - returns (address) - { - require(isValidator(account), "Not a validator"); - require(epochNumber <= getEpochNumber(), "Epoch cannot be larger than current"); - MembershipHistory storage history = validators[account].membershipHistory; - require(index < history.tail.add(history.numEntries), "index out of bounds"); - require(index >= history.tail && history.numEntries > 0, "index out of bounds"); - bool isExactMatch = history.entries[index].epochNumber == epochNumber; - bool isLastEntry = index.sub(history.tail) == history.numEntries.sub(1); - bool isWithinRange = history.entries[index].epochNumber < epochNumber && - (history.entries[index.add(1)].epochNumber > epochNumber || isLastEntry); - require( - isExactMatch || isWithinRange, - "provided index does not match provided epochNumber at index in history." - ); - return history.entries[index].group; - } - -} diff --git a/packages/protocol/contracts/governance/interfaces/IElection.sol b/packages/protocol/contracts/governance/interfaces/IElection.sol deleted file mode 100644 index 67f3a1169..000000000 --- a/packages/protocol/contracts/governance/interfaces/IElection.sol +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.5.13 <0.9.0; - -interface IElection { - function electValidatorSigners() external view returns (address[] memory); - function electNValidatorSigners(uint256, uint256) external view returns (address[] memory); - function vote(address, uint256, address, address) external returns (bool); - function activate(address) external returns (bool); - function revokeActive(address, uint256, address, address, uint256) external returns (bool); - function revokeAllActive(address, address, address, uint256) external returns (bool); - function revokePending(address, uint256, address, address, uint256) external returns (bool); - function markGroupIneligible(address) external; - function markGroupEligible(address, address, address) external; - function allowedToVoteOverMaxNumberOfGroups(address) external returns (bool); - function forceDecrementVotes( - address, - uint256, - address[] calldata, - address[] calldata, - uint256[] calldata - ) external returns (uint256); - function setAllowedToVoteOverMaxNumberOfGroups(bool flag) external; - - // view functions - function getElectableValidators() external view returns (uint256, uint256); - function getElectabilityThreshold() external view returns (uint256); - function getNumVotesReceivable(address) external view returns (uint256); - function getTotalVotes() external view returns (uint256); - function getActiveVotes() external view returns (uint256); - function getTotalVotesByAccount(address) external view returns (uint256); - function getPendingVotesForGroupByAccount(address, address) external view returns (uint256); - function getActiveVotesForGroupByAccount(address, address) external view returns (uint256); - function getTotalVotesForGroupByAccount(address, address) external view returns (uint256); - function getActiveVoteUnitsForGroupByAccount(address, address) external view returns (uint256); - function getTotalVotesForGroup(address) external view returns (uint256); - function getActiveVotesForGroup(address) external view returns (uint256); - function getPendingVotesForGroup(address) external view returns (uint256); - function getGroupEligibility(address) external view returns (bool); - function getGroupEpochRewards(address, uint256, uint256[] calldata) - external - view - returns (uint256); - function getGroupsVotedForByAccount(address) external view returns (address[] memory); - function getEligibleValidatorGroups() external view returns (address[] memory); - function getTotalVotesForEligibleValidatorGroups() - external - view - returns (address[] memory, uint256[] memory); - function getCurrentValidatorSigners() external view returns (address[] memory); - function canReceiveVotes(address, uint256) external view returns (bool); - function hasActivatablePendingVotes(address, address) external view returns (bool); - function validatorSignerAddressFromCurrentSet(uint256 index) external view returns (address); - function numberValidatorsInCurrentSet() external view returns (uint256); - - // only owner - function setElectableValidators(uint256, uint256) external returns (bool); - function setMaxNumGroupsVotedFor(uint256) external returns (bool); - function setElectabilityThreshold(uint256) external returns (bool); - - // only VM - function distributeEpochRewards(address, uint256, address, address) external; -} diff --git a/packages/protocol/contracts/governance/interfaces/IGovernance.sol b/packages/protocol/contracts/governance/interfaces/IGovernance.sol deleted file mode 100644 index 210d2efac..000000000 --- a/packages/protocol/contracts/governance/interfaces/IGovernance.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.5.13 <0.9.0; - -interface IGovernance { - function removeVotesWhenRevokingDelegatedVotes(address account, uint256 maxAmountAllowed) - external; - function votePartially( - uint256 proposalId, - uint256 index, - uint256 yesVotes, - uint256 noVotes, - uint256 abstainVotes - ) external returns (bool); - - function isVoting(address) external view returns (bool); - function getAmountOfGoldUsedForVoting(address account) external view returns (uint256); - - function getProposal(uint256 proposalId) - external - view - returns (address, uint256, uint256, uint256, string memory, uint256, bool); - - function getReferendumStageDuration() external view returns (uint256); -} diff --git a/packages/protocol/contracts/governance/interfaces/ILockedGold.sol b/packages/protocol/contracts/governance/interfaces/ILockedGold.sol deleted file mode 100644 index 1e191e6e8..000000000 --- a/packages/protocol/contracts/governance/interfaces/ILockedGold.sol +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.5.13 <0.9.0; - -interface ILockedGold { - function lock() external payable; - function incrementNonvotingAccountBalance(address, uint256) external; - function decrementNonvotingAccountBalance(address, uint256) external; - function getAccountTotalLockedGold(address) external view returns (uint256); - function getTotalLockedGold() external view returns (uint256); - function getPendingWithdrawals(address) - external - view - returns (uint256[] memory, uint256[] memory); - function getPendingWithdrawal(address account, uint256 index) - external - view - returns (uint256, uint256); - function getTotalPendingWithdrawals(address) external view returns (uint256); - function unlock(uint256) external; - function relock(uint256, uint256) external; - function withdraw(uint256) external; - function slash( - address account, - uint256 penalty, - address reporter, - uint256 reward, - address[] calldata lessers, - address[] calldata greaters, - uint256[] calldata indices - ) external; - function isSlasher(address) external view returns (bool); - - function getAccountTotalDelegatedFraction(address account) external view returns (uint256); - - function getAccountTotalGovernanceVotingPower(address account) external view returns (uint256); - function unlockingPeriod() external view returns (uint256); - function getAccountNonvotingLockedGold(address account) external view returns (uint256); -} diff --git a/packages/protocol/contracts/governance/interfaces/IReleaseGold.sol b/packages/protocol/contracts/governance/interfaces/IReleaseGold.sol deleted file mode 100644 index d2b6b45f0..000000000 --- a/packages/protocol/contracts/governance/interfaces/IReleaseGold.sol +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.5.13 <0.9.0; - -interface IReleaseGold { - function transfer(address, uint256) external; - function unlockGold(uint256) external; - function withdrawLockedGold(uint256) external; - function authorizeVoteSigner(address payable, uint8, bytes32, bytes32) external; - function authorizeValidatorSigner(address payable, uint8, bytes32, bytes32) external; - function authorizeValidatorSignerWithPublicKey( - address payable, - uint8, - bytes32, - bytes32, - bytes calldata - ) external; - function authorizeValidatorSignerWithKeys( - address payable, - uint8, - bytes32, - bytes32, - bytes calldata, - bytes calldata, - bytes calldata - ) external; - function authorizeAttestationSigner(address payable, uint8, bytes32, bytes32) external; - function revokeActive(address, uint256, address, address, uint256) external; - function revokePending(address, uint256, address, address, uint256) external; - - // view functions - function getTotalBalance() external view returns (uint256); - function getRemainingTotalBalance() external view returns (uint256); - function getRemainingUnlockedBalance() external view returns (uint256); - function getRemainingLockedBalance() external view returns (uint256); - function getCurrentReleasedTotalAmount() external view returns (uint256); - function isRevoked() external view returns (bool); - - // only beneficiary - function setCanExpire(bool) external; - function withdraw(uint256) external; - function lockGold(uint256) external; - function relockGold(uint256, uint256) external; - function setAccount(string calldata, bytes calldata, address, uint8, bytes32, bytes32) external; - function createAccount() external; - function setAccountName(string calldata) external; - function setAccountWalletAddress(address, uint8, bytes32, bytes32) external; - function setAccountDataEncryptionKey(bytes calldata) external; - function setAccountMetadataURL(string calldata) external; - - // only owner - function setBeneficiary(address payable) external; - - // only release owner - function setLiquidityProvision() external; - function setMaxDistribution(uint256) external; - function refundAndFinalize() external; - function revoke() external; - function expire() external; -} diff --git a/packages/protocol/contracts/governance/interfaces/IValidators.sol b/packages/protocol/contracts/governance/interfaces/IValidators.sol deleted file mode 100644 index 907dbaa1d..000000000 --- a/packages/protocol/contracts/governance/interfaces/IValidators.sol +++ /dev/null @@ -1,85 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.5.13 <0.9.0; - -interface IValidators { - function registerValidator(bytes calldata, bytes calldata, bytes calldata) - external - returns (bool); - function deregisterValidator(uint256) external returns (bool); - function affiliate(address) external returns (bool); - function deaffiliate() external returns (bool); - function updateBlsPublicKey(bytes calldata, bytes calldata) external returns (bool); - function registerValidatorGroup(uint256) external returns (bool); - function deregisterValidatorGroup(uint256) external returns (bool); - function addMember(address) external returns (bool); - function addFirstMember(address, address, address) external returns (bool); - function removeMember(address) external returns (bool); - function reorderMember(address, address, address) external returns (bool); - function updateCommission() external; - function setNextCommissionUpdate(uint256) external; - function resetSlashingMultiplier() external; - - // only owner - function setCommissionUpdateDelay(uint256) external; - function setMaxGroupSize(uint256) external returns (bool); - function setMembershipHistoryLength(uint256) external returns (bool); - function setValidatorScoreParameters(uint256, uint256) external returns (bool); - function setGroupLockedGoldRequirements(uint256, uint256) external returns (bool); - function setValidatorLockedGoldRequirements(uint256, uint256) external returns (bool); - function setSlashingMultiplierResetPeriod(uint256) external; - - // view functions - function getMaxGroupSize() external view returns (uint256); - function getCommissionUpdateDelay() external view returns (uint256); - function getValidatorScoreParameters() external view returns (uint256, uint256); - function getMembershipHistory(address) - external - view - returns (uint256[] memory, address[] memory, uint256, uint256); - function calculateEpochScore(uint256) external view returns (uint256); - function calculateGroupEpochScore(uint256[] calldata) external view returns (uint256); - function getAccountLockedGoldRequirement(address) external view returns (uint256); - function meetsAccountLockedGoldRequirements(address) external view returns (bool); - function getValidatorBlsPublicKeyFromSigner(address) external view returns (bytes memory); - function getValidator(address account) - external - view - returns (bytes memory, bytes memory, address, uint256, address); - function getValidatorGroup(address) - external - view - returns (address[] memory, uint256, uint256, uint256, uint256[] memory, uint256, uint256); - function getGroupNumMembers(address) external view returns (uint256); - function getTopGroupValidators(address, uint256) external view returns (address[] memory); - function getGroupsNumMembers(address[] calldata accounts) - external - view - returns (uint256[] memory); - function getNumRegisteredValidators() external view returns (uint256); - function groupMembershipInEpoch(address, uint256, uint256) external view returns (address); - - // only registered contract - function updateEcdsaPublicKey(address, address, bytes calldata) external returns (bool); - function updatePublicKeys(address, address, bytes calldata, bytes calldata, bytes calldata) - external - returns (bool); - function getValidatorLockedGoldRequirements() external view returns (uint256, uint256); - function getGroupLockedGoldRequirements() external view returns (uint256, uint256); - function getRegisteredValidators() external view returns (address[] memory); - function getRegisteredValidatorSigners() external view returns (address[] memory); - function getRegisteredValidatorGroups() external view returns (address[] memory); - function isValidatorGroup(address) external view returns (bool); - function isValidator(address) external view returns (bool); - function getValidatorGroupSlashingMultiplier(address) external view returns (uint256); - function getMembershipInLastEpoch(address) external view returns (address); - function getMembershipInLastEpochFromSigner(address) external view returns (address); - - // only VM - function updateValidatorScoreFromSigner(address, uint256) external; - function distributeEpochPaymentsFromSigner(address, uint256) external returns (uint256); - - // only slasher - function forceDeaffiliateIfValidator(address) external; - function halveSlashingMultiplier(address) external; - -} diff --git a/packages/protocol/contracts/governance/proxies/BlockchainParametersProxy.sol b/packages/protocol/contracts/governance/proxies/BlockchainParametersProxy.sol deleted file mode 100644 index 6d352157e..000000000 --- a/packages/protocol/contracts/governance/proxies/BlockchainParametersProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../../common/Proxy.sol"; - -/* solhint-disable-next-line no-empty-blocks */ -contract BlockchainParametersProxy is Proxy {} diff --git a/packages/protocol/contracts/governance/proxies/DoubleSigningSlasherProxy.sol b/packages/protocol/contracts/governance/proxies/DoubleSigningSlasherProxy.sol deleted file mode 100644 index 89ee34033..000000000 --- a/packages/protocol/contracts/governance/proxies/DoubleSigningSlasherProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../../common/Proxy.sol"; - -/* solhint-disable-next-line no-empty-blocks */ -contract DoubleSigningSlasherProxy is Proxy {} diff --git a/packages/protocol/contracts/governance/proxies/DowntimeSlasherProxy.sol b/packages/protocol/contracts/governance/proxies/DowntimeSlasherProxy.sol deleted file mode 100644 index 4371585b4..000000000 --- a/packages/protocol/contracts/governance/proxies/DowntimeSlasherProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../../common/Proxy.sol"; - -/* solhint-disable-next-line no-empty-blocks */ -contract DowntimeSlasherProxy is Proxy {} diff --git a/packages/protocol/contracts/governance/proxies/ElectionProxy.sol b/packages/protocol/contracts/governance/proxies/ElectionProxy.sol deleted file mode 100644 index 4c03eadde..000000000 --- a/packages/protocol/contracts/governance/proxies/ElectionProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../../common/Proxy.sol"; - -/* solhint-disable-next-line no-empty-blocks */ -contract ElectionProxy is Proxy {} diff --git a/packages/protocol/contracts/governance/proxies/EpochRewardsProxy.sol b/packages/protocol/contracts/governance/proxies/EpochRewardsProxy.sol deleted file mode 100644 index d90ba3fbf..000000000 --- a/packages/protocol/contracts/governance/proxies/EpochRewardsProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../../common/Proxy.sol"; - -/* solhint-disable-next-line no-empty-blocks */ -contract EpochRewardsProxy is Proxy {} diff --git a/packages/protocol/contracts/governance/proxies/GovernanceApproverMultiSigProxy.sol b/packages/protocol/contracts/governance/proxies/GovernanceApproverMultiSigProxy.sol deleted file mode 100644 index 7da7e13d0..000000000 --- a/packages/protocol/contracts/governance/proxies/GovernanceApproverMultiSigProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../../common/Proxy.sol"; - -/* solhint-disable-next-line no-empty-blocks */ -contract GovernanceApproverMultiSigProxy is Proxy {} diff --git a/packages/protocol/contracts/governance/proxies/GovernanceProxy.sol b/packages/protocol/contracts/governance/proxies/GovernanceProxy.sol deleted file mode 100644 index 1783f6a25..000000000 --- a/packages/protocol/contracts/governance/proxies/GovernanceProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../../common/Proxy.sol"; - -/* solhint-disable-next-line no-empty-blocks */ -contract GovernanceProxy is Proxy {} diff --git a/packages/protocol/contracts/governance/proxies/GovernanceSlasherProxy.sol b/packages/protocol/contracts/governance/proxies/GovernanceSlasherProxy.sol deleted file mode 100644 index b51d14e08..000000000 --- a/packages/protocol/contracts/governance/proxies/GovernanceSlasherProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../../common/Proxy.sol"; - -/* solhint-disable-next-line no-empty-blocks */ -contract GovernanceSlasherProxy is Proxy {} diff --git a/packages/protocol/contracts/governance/proxies/LockedGoldProxy.sol b/packages/protocol/contracts/governance/proxies/LockedGoldProxy.sol deleted file mode 100644 index 8869b7918..000000000 --- a/packages/protocol/contracts/governance/proxies/LockedGoldProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../../common/Proxy.sol"; - -/* solhint-disable-next-line no-empty-blocks */ -contract LockedGoldProxy is Proxy {} diff --git a/packages/protocol/contracts/governance/proxies/ReleaseGoldMultiSigProxy.sol b/packages/protocol/contracts/governance/proxies/ReleaseGoldMultiSigProxy.sol deleted file mode 100644 index 1036ea2c9..000000000 --- a/packages/protocol/contracts/governance/proxies/ReleaseGoldMultiSigProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../../common/Proxy.sol"; - -/* solhint-disable-next-line no-empty-blocks */ -contract ReleaseGoldMultiSigProxy is Proxy {} diff --git a/packages/protocol/contracts/governance/proxies/ReleaseGoldProxy.sol b/packages/protocol/contracts/governance/proxies/ReleaseGoldProxy.sol deleted file mode 100644 index cee0c6252..000000000 --- a/packages/protocol/contracts/governance/proxies/ReleaseGoldProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../../common/Proxy.sol"; - -/* solhint-disable-next-line no-empty-blocks */ -contract ReleaseGoldProxy is Proxy {} diff --git a/packages/protocol/contracts/governance/proxies/ValidatorsProxy.sol b/packages/protocol/contracts/governance/proxies/ValidatorsProxy.sol deleted file mode 100644 index dda472e8b..000000000 --- a/packages/protocol/contracts/governance/proxies/ValidatorsProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../../common/Proxy.sol"; - -/* solhint-disable-next-line no-empty-blocks */ -contract ValidatorsProxy is Proxy {} diff --git a/packages/protocol/contracts/governance/test/BlockchainParametersTest.sol b/packages/protocol/contracts/governance/test/BlockchainParametersTest.sol deleted file mode 100644 index 286266d52..000000000 --- a/packages/protocol/contracts/governance/test/BlockchainParametersTest.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../BlockchainParameters.sol"; -import "./MockUsingPrecompiles.sol"; - -contract BlockchainParametersTest is BlockchainParameters(true), MockUsingPrecompiles {} diff --git a/packages/protocol/contracts/governance/test/DoubleSigningSlasherTest.sol b/packages/protocol/contracts/governance/test/DoubleSigningSlasherTest.sol deleted file mode 100644 index cc489c282..000000000 --- a/packages/protocol/contracts/governance/test/DoubleSigningSlasherTest.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../DoubleSigningSlasher.sol"; -import "./MockUsingPrecompiles.sol"; - -contract DoubleSigningSlasherTest is DoubleSigningSlasher(true), MockUsingPrecompiles {} diff --git a/packages/protocol/contracts/governance/test/DowntimeSlasherTest.sol b/packages/protocol/contracts/governance/test/DowntimeSlasherTest.sol deleted file mode 100644 index c3749b10d..000000000 --- a/packages/protocol/contracts/governance/test/DowntimeSlasherTest.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../DowntimeSlasher.sol"; -import "./MockUsingPrecompiles.sol"; - -contract DowntimeSlasherTest is DowntimeSlasher(true), MockUsingPrecompiles {} diff --git a/packages/protocol/contracts/governance/test/ElectionTest.sol b/packages/protocol/contracts/governance/test/ElectionTest.sol deleted file mode 100644 index 27398ab19..000000000 --- a/packages/protocol/contracts/governance/test/ElectionTest.sol +++ /dev/null @@ -1,15 +0,0 @@ -pragma solidity ^0.5.13; - -import "../Election.sol"; -import "../../common/FixidityLib.sol"; - -/** - * @title A wrapper around Election that exposes onlyVm functions for testing. - */ -contract ElectionTest is Election(true) { - function distributeEpochRewards(address group, uint256 value, address lesser, address greater) - external - { - return _distributeEpochRewards(group, value, lesser, greater); - } -} diff --git a/packages/protocol/contracts/governance/test/EpochRewardsTest.sol b/packages/protocol/contracts/governance/test/EpochRewardsTest.sol deleted file mode 100644 index 78593135c..000000000 --- a/packages/protocol/contracts/governance/test/EpochRewardsTest.sol +++ /dev/null @@ -1,26 +0,0 @@ -pragma solidity ^0.5.13; - -import "../EpochRewards.sol"; - -/** - * @title A wrapper around EpochRewards that exposes internal functions for testing. - */ -contract EpochRewardsTest is EpochRewards(true) { - uint256 private numValidatorsInCurrentSet; - function getRewardsMultiplier(uint256 targetGoldTotalSupplyIncrease) - external - view - returns (uint256) - { - return _getRewardsMultiplier(targetGoldTotalSupplyIncrease).unwrap(); - } - - // mocks the precompile - function numberValidatorsInCurrentSet() public view returns (uint256) { - return numValidatorsInCurrentSet; - } - - function setNumberValidatorsInCurrentSet(uint256 value) external { - numValidatorsInCurrentSet = value; - } -} diff --git a/packages/protocol/contracts/governance/test/GovernanceTest.sol b/packages/protocol/contracts/governance/test/GovernanceTest.sol deleted file mode 100644 index 04070aa90..000000000 --- a/packages/protocol/contracts/governance/test/GovernanceTest.sol +++ /dev/null @@ -1,40 +0,0 @@ -pragma solidity ^0.5.13; - -import "../Governance.sol"; - -contract GovernanceTest is Governance(true) { - address[] validatorSet; - - // Minimally override core functions from UsingPrecompiles - function numberValidatorsInCurrentSet() public view returns (uint256) { - return validatorSet.length; - } - - function numberValidatorsInSet(uint256) public view returns (uint256) { - return validatorSet.length; - } - - function validatorSignerAddressFromCurrentSet(uint256 index) public view returns (address) { - return validatorSet[index]; - } - - // Expose test utilities - function addValidator(address validator) external { - validatorSet.push(validator); - } - - // exposes removeVotesWhenRevokingDelegatedVotes for tests - function removeVotesWhenRevokingDelegatedVotesTest(address account, uint256 maxAmountAllowed) - public - { - _removeVotesWhenRevokingDelegatedVotes(account, maxAmountAllowed); - } - - function setDeprecatedWeight(address voterAddress, uint256 proposalIndex, uint256 weight) - external - { - Voter storage voter = voters[voterAddress]; - VoteRecord storage voteRecord = voter.referendumVotes[proposalIndex]; - voteRecord.deprecated_weight = weight; - } -} diff --git a/packages/protocol/contracts/governance/test/MockElection.sol b/packages/protocol/contracts/governance/test/MockElection.sol deleted file mode 100644 index 52e4061a2..000000000 --- a/packages/protocol/contracts/governance/test/MockElection.sol +++ /dev/null @@ -1,84 +0,0 @@ -pragma solidity ^0.5.13; - -/** - * @title Holds a list of addresses of validators - */ -contract MockElection { - mapping(address => bool) public isIneligible; - mapping(address => bool) public isEligible; - mapping(address => bool) public allowedToVoteOverMaxNumberOfGroups; - address[] public electedValidators; - uint256 active; - uint256 total; - - function markGroupIneligible(address account) external { - isIneligible[account] = true; - } - - function markGroupEligible(address account, address, address) external { - isEligible[account] = true; - } - - function getTotalVotes() external view returns (uint256) { - return total; - } - - function getActiveVotes() external view returns (uint256) { - return active; - } - - function getTotalVotesByAccount(address) external view returns (uint256) { - return 0; - } - - function setActiveVotes(uint256 value) external { - active = value; - } - - function setTotalVotes(uint256 value) external { - total = value; - } - - function setElectedValidators(address[] calldata _electedValidators) external { - electedValidators = _electedValidators; - } - - function electValidatorSigners() external view returns (address[] memory) { - return electedValidators; - } - - function vote(address, uint256, address, address) external returns (bool) { - return true; - } - - function activate(address) external returns (bool) { - return true; - } - - function revokeAllActive(address, address, address, uint256) external returns (bool) { - return true; - } - - function revokeActive(address, uint256, address, address, uint256) external returns (bool) { - return true; - } - - function revokePending(address, uint256, address, address, uint256) external returns (bool) { - return true; - } - - function setAllowedToVoteOverMaxNumberOfGroups(address account, bool flag) public { - allowedToVoteOverMaxNumberOfGroups[account] = flag; - } - - function forceDecrementVotes( - address, - uint256 value, - address[] calldata, - address[] calldata, - uint256[] calldata - ) external returns (uint256) { - this.setActiveVotes(this.getActiveVotes() - value); - return value; - } -} diff --git a/packages/protocol/contracts/governance/test/MockGovernance.sol b/packages/protocol/contracts/governance/test/MockGovernance.sol deleted file mode 100644 index 7b660089f..000000000 --- a/packages/protocol/contracts/governance/test/MockGovernance.sol +++ /dev/null @@ -1,54 +0,0 @@ -pragma solidity ^0.5.13; - -import "../interfaces/IGovernance.sol"; - -/** - * @title A mock Governance for testing. - */ -contract MockGovernance is IGovernance { - mapping(address => bool) public isVoting; - mapping(address => uint256) public totalVotes; - mapping(address => uint256) public removeVotesCalledFor; - - function() external payable {} // solhint-disable no-empty-blocks - - function setVoting(address voter) external { - isVoting[voter] = true; - } - - function setTotalVotes(address voter, uint256 votes) external { - totalVotes[voter] = votes; - } - - function getAmountOfGoldUsedForVoting(address account) external view returns (uint256) { - return totalVotes[account]; - } - - function removeVotesWhenRevokingDelegatedVotes(address account, uint256 maxAmountAllowed) - external - { - removeVotesCalledFor[account] = maxAmountAllowed; - } - - function votePartially( - uint256 proposalId, - uint256 index, - uint256 yesVotes, - uint256 noVotes, - uint256 abstainVotes - ) external returns (bool) { - return true; - } - - function getProposal(uint256 proposalId) - external - view - returns (address, uint256, uint256, uint256, string memory, uint256, bool) - { - return (address(0), 0, 0, 0, "", 0, false); - } - - function getReferendumStageDuration() external view returns (uint256) { - return 0; - } -} diff --git a/packages/protocol/contracts/governance/test/MockLockedGold.sol b/packages/protocol/contracts/governance/test/MockLockedGold.sol deleted file mode 100644 index 4b41530df..000000000 --- a/packages/protocol/contracts/governance/test/MockLockedGold.sol +++ /dev/null @@ -1,131 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; - -import "../interfaces/ILockedGold.sol"; - -/** - * @title A mock LockedGold for testing. - */ -contract MockLockedGold is ILockedGold { - using SafeMath for uint256; - - struct Authorizations { - address validator; - address voter; - } - - mapping(address => uint256) public accountTotalLockedGold; - mapping(address => uint256) public nonvotingAccountBalance; - mapping(address => address) public authorizedValidators; - mapping(address => address) public authorizedBy; - uint256 private totalLockedGold; - mapping(address => bool) public slashingWhitelist; - mapping(address => uint256) public totalGovernancePower; - mapping(address => uint256) public accountTotalDelegatedAmountInPercents; - - function incrementNonvotingAccountBalance(address account, uint256 value) external { - nonvotingAccountBalance[account] = nonvotingAccountBalance[account].add(value); - } - - function decrementNonvotingAccountBalance(address account, uint256 value) public { - nonvotingAccountBalance[account] = nonvotingAccountBalance[account].sub(value); - } - - function setAccountTotalLockedGold(address account, uint256 value) external { - accountTotalLockedGold[account] = value; - } - - function setAccountTotalDelegatedAmountInPercents(address account, uint256 value) external { - accountTotalDelegatedAmountInPercents[account] = value; - } - - function setAccountTotalGovernancePower(address account, uint256 value) external { - totalGovernancePower[account] = value; - } - - function getAccountTotalLockedGold(address account) external view returns (uint256) { - return accountTotalLockedGold[account]; - } - - function setTotalLockedGold(uint256 value) external { - totalLockedGold = value; - } - function getTotalLockedGold() external view returns (uint256) { - return totalLockedGold; - } - - function lock() external payable { - accountTotalLockedGold[msg.sender] = accountTotalLockedGold[msg.sender].add(msg.value); - } - - function unlock(uint256 value) external { - accountTotalLockedGold[msg.sender] = accountTotalLockedGold[msg.sender].sub(value); - } - - function relock(uint256 index, uint256 value) external { - // TODO: add implementation if necessary to mock behaviour - } - - function withdraw(uint256 index) external { - // TODO: add implementation if necessary to mock behaviour - } - - function slash( - address account, - uint256 penalty, - address, - uint256, - address[] calldata, - address[] calldata, - uint256[] calldata - ) external { - accountTotalLockedGold[account] = accountTotalLockedGold[account].sub(penalty); - } - function addSlasher(address slasher) external { - slashingWhitelist[slasher] = true; - } - function removeSlasher(address slasher) external { - slashingWhitelist[slasher] = false; - } - function isSlasher(address slasher) external view returns (bool) { - return slashingWhitelist[slasher]; - } - - function getPendingWithdrawals(address) - external - view - returns (uint256[] memory, uint256[] memory) - { - uint256[] memory empty = new uint256[](0); - return (empty, empty); - } - - function getTotalPendingWithdrawals(address) external view returns (uint256) { - return 0; - } - - function getAccountTotalDelegatedFraction(address account) external view returns (uint256) { - return accountTotalDelegatedAmountInPercents[account]; - } - - function getAccountTotalGovernanceVotingPower(address account) external view returns (uint256) { - return totalGovernancePower[account]; - } - - function getPendingWithdrawal(address account, uint256 index) - external - view - returns (uint256, uint256) - { - return (0, 0); - } - - function unlockingPeriod() external view returns (uint256) { - return 0; - } - - function getAccountNonvotingLockedGold(address account) external view returns (uint256) { - return 0; - } -} diff --git a/packages/protocol/contracts/governance/test/MockUsingPrecompiles.sol b/packages/protocol/contracts/governance/test/MockUsingPrecompiles.sol deleted file mode 100644 index 4595166f6..000000000 --- a/packages/protocol/contracts/governance/test/MockUsingPrecompiles.sol +++ /dev/null @@ -1,72 +0,0 @@ -pragma solidity ^0.5.13; - -import "../DoubleSigningSlasher.sol"; - -contract MockUsingPrecompiles { - mapping(bytes32 => bytes32) verifiedSealBitmap; - mapping(uint256 => bytes32) parentSealBitmap; - mapping(bytes32 => address) epochSigner; - - uint256 numValidators; - - function setVerifiedSealBitmap(bytes memory header, bytes32 bitmap) public { - verifiedSealBitmap[keccak256(abi.encodePacked(header))] = bitmap; - } - - function getVerifiedSealBitmapFromHeader(bytes memory header) public view returns (bytes32) { - return verifiedSealBitmap[keccak256(abi.encodePacked(header))]; - } - - function getParentSealBitmap(uint256 blockNumber) public view returns (bytes32) { - return parentSealBitmap[blockNumber]; - } - - function setParentSealBitmap(uint256 blockNumber, bytes32 bitmap) public { - parentSealBitmap[blockNumber] = bitmap; - } - - function calcEpoch(uint256 blockNumber) internal pure returns (uint256) { - uint256 epochSize = 100; - // Follows GetEpochNumber from celo-blockchain/blob/master/consensus/istanbul/utils.go - uint256 epochNumber = blockNumber / epochSize; - if (blockNumber % epochSize == 0) { - return epochNumber; - } else { - return epochNumber + 1; - } - } - - function validatorSignerAddressFromSet(uint256 index, uint256 blockNumber) - public - view - returns (address) - { - return epochSigner[keccak256(abi.encodePacked(calcEpoch(blockNumber), index))]; - } - - function setEpochSigner(uint256 epoch, uint256 index, address signer) public { - epochSigner[keccak256(abi.encodePacked(epoch, index))] = signer; - } - - function setNumberValidators(uint256 num) public { - numValidators = num; - } - - function numberValidatorsInSet(uint256) public view returns (uint256) { - return numValidators; - } - - mapping(bytes32 => uint256) blockNumbers; - - function getBlockNumberFromHeader(bytes memory header) public view returns (uint256) { - return blockNumbers[keccak256(abi.encodePacked(header))]; - } - - function setBlockNumber(bytes memory header, uint256 number) public returns (uint256) { - blockNumbers[keccak256(abi.encodePacked(header))] = number; - } - - function hashHeader(bytes memory header) public view returns (bytes32) { - return keccak256(header); - } -} diff --git a/packages/protocol/contracts/governance/test/MockValidators.sol b/packages/protocol/contracts/governance/test/MockValidators.sol deleted file mode 100644 index 8757e817f..000000000 --- a/packages/protocol/contracts/governance/test/MockValidators.sol +++ /dev/null @@ -1,113 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; - -/** - * @title Holds a list of addresses of validators - */ -contract MockValidators { - using SafeMath for uint256; - - uint256 private constant FIXED1_UINT = 1000000000000000000000000; - - mapping(address => bool) public isValidator; - mapping(address => bool) public isValidatorGroup; - mapping(address => uint256) private numGroupMembers; - mapping(address => uint256) private lockedGoldRequirements; - mapping(address => bool) private doesNotMeetAccountLockedGoldRequirements; - mapping(address => address[]) private members; - mapping(address => address) private affiliations; - uint256 private numRegisteredValidators; - - function updateEcdsaPublicKey(address, address, bytes calldata) external returns (bool) { - return true; - } - - function updatePublicKeys(address, address, bytes calldata, bytes calldata, bytes calldata) - external - returns (bool) - { - return true; - } - - function setValidator(address account) external { - isValidator[account] = true; - } - - function setValidatorGroup(address group) external { - isValidatorGroup[group] = true; - } - - function affiliate(address group) external returns (bool) { - affiliations[msg.sender] = group; - return true; - } - - function setDoesNotMeetAccountLockedGoldRequirements(address account) external { - doesNotMeetAccountLockedGoldRequirements[account] = true; - } - - function meetsAccountLockedGoldRequirements(address account) external view returns (bool) { - return !doesNotMeetAccountLockedGoldRequirements[account]; - } - - function getGroupNumMembers(address group) public view returns (uint256) { - return members[group].length; - } - - function setNumRegisteredValidators(uint256 value) external { - numRegisteredValidators = value; - } - - function getNumRegisteredValidators() external view returns (uint256) { - return numRegisteredValidators; - } - - function setMembers(address group, address[] calldata _members) external { - members[group] = _members; - } - - function setAccountLockedGoldRequirement(address account, uint256 value) external { - lockedGoldRequirements[account] = value; - } - - function getAccountLockedGoldRequirement(address account) external view returns (uint256) { - return lockedGoldRequirements[account]; - } - - function calculateGroupEpochScore(uint256[] calldata uptimes) external view returns (uint256) { - return uptimes[0]; - } - - function getTopGroupValidators(address group, uint256 n) - external - view - returns (address[] memory) - { - require(n <= members[group].length); - address[] memory validators = new address[](n); - for (uint256 i = 0; i < n; i = i.add(1)) { - validators[i] = members[group][i]; - } - return validators; - } - - function getGroupsNumMembers(address[] calldata groups) external view returns (uint256[] memory) { - uint256[] memory numMembers = new uint256[](groups.length); - for (uint256 i = 0; i < groups.length; i = i.add(1)) { - numMembers[i] = getGroupNumMembers(groups[i]); - } - return numMembers; - } - - function groupMembershipInEpoch(address addr, uint256, uint256) external view returns (address) { - return affiliations[addr]; - } - - function halveSlashingMultiplier(address) external {} - - function forceDeaffiliateIfValidator(address validator) external {} - function getValidatorGroupSlashingMultiplier(address) external view returns (uint256) { - return FIXED1_UINT; - } -} diff --git a/packages/protocol/contracts/governance/test/TestTransactions.sol b/packages/protocol/contracts/governance/test/TestTransactions.sol deleted file mode 100644 index 8f545a0ac..000000000 --- a/packages/protocol/contracts/governance/test/TestTransactions.sol +++ /dev/null @@ -1,17 +0,0 @@ -pragma solidity ^0.5.13; - -/** - * @title A contract for transaction testing. - */ -contract TestTransactions { - mapping(uint256 => uint256) public values; - - function getValue(uint256 key) external view returns (uint256) { - return values[key]; - } - - function setValue(uint256 key, uint256 value, bool shouldSucceed) external { - require(shouldSucceed); - values[key] = value; - } -} diff --git a/packages/protocol/contracts/governance/test/ValidatorsTest.sol b/packages/protocol/contracts/governance/test/ValidatorsTest.sol deleted file mode 100644 index d61690850..000000000 --- a/packages/protocol/contracts/governance/test/ValidatorsTest.sol +++ /dev/null @@ -1,20 +0,0 @@ -pragma solidity ^0.5.13; - -import "../Validators.sol"; -import "../../common/FixidityLib.sol"; - -/** - * @title A wrapper around Validators that exposes onlyVm functions for testing. - */ -contract ValidatorsTest is Validators(true) { - function updateValidatorScoreFromSigner(address signer, uint256 uptime) external { - return _updateValidatorScoreFromSigner(signer, uptime); - } - - function distributeEpochPaymentsFromSigner(address signer, uint256 maxPayment) - external - returns (uint256) - { - return _distributeEpochPaymentsFromSigner(signer, maxPayment); - } -} diff --git a/packages/protocol/contracts/identity/Attestations.sol b/packages/protocol/contracts/identity/Attestations.sol deleted file mode 100644 index af5417a51..000000000 --- a/packages/protocol/contracts/identity/Attestations.sol +++ /dev/null @@ -1,541 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; -import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; -import "openzeppelin-solidity/contracts/utils/SafeCast.sol"; - -import "./interfaces/IAttestations.sol"; -import "../common/interfaces/IAccounts.sol"; -import "../common/interfaces/ICeloVersionedContract.sol"; - -import "../common/Initializable.sol"; -import "../common/UsingRegistry.sol"; -import "../common/Signatures.sol"; -import "../common/UsingPrecompiles.sol"; -import "../common/libraries/ReentrancyGuard.sol"; - -/** - * @title Contract mapping identifiers to accounts - */ -contract Attestations is - IAttestations, - ICeloVersionedContract, - Ownable, - Initializable, - UsingRegistry, - ReentrancyGuard, - UsingPrecompiles -{ - using SafeMath for uint256; - using SafeCast for uint256; - - enum AttestationStatus { None, Incomplete, Complete } - - struct Attestation { - AttestationStatus status; - // For outstanding attestations, this is the block number of the request. - // For completed attestations, this is the block number of the attestation completion. - uint32 blockNumber; - // The token with which attestation request fees were paid. - address attestationRequestFeeToken; - } - - // Stores attestations state for a single (identifier, account address) pair. - struct AttestedAddress { - // Total number of requested attestations. - uint32 requested; - // Total number of completed attestations. - uint32 completed; - // List of selected issuers responsible for attestations. The length of this list - // might be smaller than `requested` (which represents the total number of requested - // attestations) if users are not calling `selectIssuers` on unselected requests. - address[] selectedIssuers; - // State of each attestation keyed by issuer. - mapping(address => Attestation) issuedAttestations; - } - - struct UnselectedRequest { - // The block at which the attestations were requested. - uint32 blockNumber; - // The number of attestations that were requested. - uint32 attestationsRequested; - // The token with which attestation request fees were paid in this request. - address attestationRequestFeeToken; - } - - struct IdentifierState { - // All account addresses associated with this identifier. - address[] accounts; - // Keeps the state of attestations for account addresses for this identifier. - mapping(address => AttestedAddress) attestations; - // Temporarily stores attestation requests for which issuers should be selected by the account. - mapping(address => UnselectedRequest) unselectedRequests; - } - - mapping(bytes32 => IdentifierState) identifiers; - - // The duration in blocks in which an attestation can be completed from the block in which the - // attestation was requested. - uint256 public attestationExpiryBlocks; - - // The duration to wait until selectIssuers can be called for an attestation request. - uint256 public selectIssuersWaitBlocks; - - // Limit the maximum number of attestations that can be requested - uint256 public maxAttestations; - - // The fees that are associated with attestations for a particular token. - mapping(address => uint256) public attestationRequestFees; - - // Maps a token and attestation issuer to the amount that they're owed. - mapping(address => mapping(address => uint256)) public pendingWithdrawals; - - // Attestation transfer approvals, keyed by user and keccak(identifier, from, to) - mapping(address => mapping(bytes32 => bool)) public transferApprovals; - - event AttestationsRequested( - bytes32 indexed identifier, - address indexed account, - uint256 attestationsRequested, - address attestationRequestFeeToken - ); - - event AttestationIssuerSelected( - bytes32 indexed identifier, - address indexed account, - address indexed issuer, - address attestationRequestFeeToken - ); - - event AttestationCompleted( - bytes32 indexed identifier, - address indexed account, - address indexed issuer - ); - - event Withdrawal(address indexed account, address indexed token, uint256 amount); - event AttestationExpiryBlocksSet(uint256 value); - event AttestationRequestFeeSet(address indexed token, uint256 value); - event SelectIssuersWaitBlocksSet(uint256 value); - event MaxAttestationsSet(uint256 value); - event AttestationsTransferred( - bytes32 indexed identifier, - address indexed fromAccount, - address indexed toAccount - ); - event TransferApproval( - address indexed approver, - bytes32 indexed indentifier, - address from, - address to, - bool approved - ); - - /** - * @notice Sets initialized == true on implementation contracts - * @param test Set to true to skip implementation initialization - */ - constructor(bool test) public Initializable(test) {} - - /** - * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. - * @param registryAddress The address of the registry core smart contract. - * @param _attestationExpiryBlocks The new limit on blocks allowed to come between requesting - * an attestation and completing it. - * @param _selectIssuersWaitBlocks The wait period in blocks to call selectIssuers on attestation - * requests. - * @param attestationRequestFeeTokens The address of tokens that fees should be payable in. - * @param attestationRequestFeeValues The corresponding fee values. - */ - function initialize( - address registryAddress, - uint256 _attestationExpiryBlocks, - uint256 _selectIssuersWaitBlocks, - uint256 _maxAttestations, - address[] calldata attestationRequestFeeTokens, - uint256[] calldata attestationRequestFeeValues - ) external initializer { - _transferOwnership(msg.sender); - setRegistry(registryAddress); - setAttestationExpiryBlocks(_attestationExpiryBlocks); - setSelectIssuersWaitBlocks(_selectIssuersWaitBlocks); - setMaxAttestations(_maxAttestations); - - require( - attestationRequestFeeTokens.length > 0 && - attestationRequestFeeTokens.length == attestationRequestFeeValues.length, - "attestationRequestFeeTokens specification was invalid" - ); - for (uint256 i = 0; i < attestationRequestFeeTokens.length; i = i.add(1)) { - setAttestationRequestFee(attestationRequestFeeTokens[i], attestationRequestFeeValues[i]); - } - } - - /** - * @notice Returns the storage, major, minor, and patch version of the contract. - * @return Storage version of the contract. - * @return Major version of the contract. - * @return Minor version of the contract. - * @return Patch version of the contract. - */ - function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { - return (1, 2, 0, 0); - } - - /** - * @notice Revokes an account for an identifier. - * @param identifier The identifier for which to revoke. - * @param index The index of the account in the accounts array. - */ - function revoke(bytes32 identifier, uint256 index) external { - uint256 numAccounts = identifiers[identifier].accounts.length; - require(index < numAccounts, "Index is invalid"); - require( - msg.sender == identifiers[identifier].accounts[index], - "Index does not match msg.sender" - ); - - uint256 newNumAccounts = numAccounts.sub(1); - if (index != newNumAccounts) { - identifiers[identifier].accounts[index] = identifiers[identifier].accounts[newNumAccounts]; - } - identifiers[identifier].accounts[newNumAccounts] = address(0x0); - identifiers[identifier].accounts.length = identifiers[identifier].accounts.length.sub(1); - } - - /** - * @notice Allows issuers to withdraw accumulated attestation rewards. - * @param token The address of the token that will be withdrawn. - * @dev Throws if msg.sender does not have any rewards to withdraw. - */ - function withdraw(address token) external { - address issuer = getAccounts().attestationSignerToAccount(msg.sender); - uint256 value = pendingWithdrawals[token][issuer]; - require(value > 0, "value was negative/zero"); - pendingWithdrawals[token][issuer] = 0; - require(IERC20(token).transfer(issuer, value), "token transfer failed"); - emit Withdrawal(issuer, token, value); - } - - /** - * @notice Returns the unselected attestation request for an identifier/account pair, if any. - * @param identifier Hash of the identifier. - * @param account Address of the account. - * @return block Block number at which was requested. - * @return number Number of unselected requests. - * @return address Address of the token with which this attestation request was paid for. - */ - function getUnselectedRequest(bytes32 identifier, address account) - external - view - returns (uint32, uint32, address) - { - return ( - identifiers[identifier].unselectedRequests[account].blockNumber, - identifiers[identifier].unselectedRequests[account].attestationsRequested, - identifiers[identifier].unselectedRequests[account].attestationRequestFeeToken - ); - } - - /** - * @notice Returns selected attestation issuers for a identifier/account pair. - * @param identifier Hash of the identifier. - * @param account Address of the account. - * @return Addresses of the selected attestation issuers. - */ - function getAttestationIssuers(bytes32 identifier, address account) - external - view - returns (address[] memory) - { - return identifiers[identifier].attestations[account].selectedIssuers; - } - - /** - * @notice Returns attestation stats for a identifier/account pair. - * @param identifier Hash of the identifier. - * @param account Address of the account. - * @return completed Number of completed attestations. - * @return requested Number of total requested attestations. - */ - function getAttestationStats(bytes32 identifier, address account) - external - view - returns (uint32, uint32) - { - return ( - identifiers[identifier].attestations[account].completed, - identifiers[identifier].attestations[account].requested - ); - } - - /** - * @notice Batch lookup function to determine attestation stats for a list of identifiers. - * @param identifiersToLookup Array of n identifiers. - * @return [0] Array of number of matching accounts per identifier. - * @return [1] Array of sum([0]) matching walletAddresses. - * @return [2] Array of sum([0]) numbers indicating the completions for each account. - * @return [3] Array of sum([0]) numbers indicating the total number of requested - attestations for each account. - */ - function batchGetAttestationStats(bytes32[] calldata identifiersToLookup) - external - view - returns (uint256[] memory, address[] memory, uint64[] memory, uint64[] memory) - { - require(identifiersToLookup.length > 0, "You have to pass at least one identifier"); - - uint256[] memory matches; - address[] memory addresses; - - (matches, addresses) = batchlookupAccountsForIdentifier(identifiersToLookup); - - uint64[] memory completed = new uint64[](addresses.length); - uint64[] memory total = new uint64[](addresses.length); - - uint256 currentIndex = 0; - for (uint256 i = 0; i < identifiersToLookup.length; i = i.add(1)) { - address[] memory addrs = identifiers[identifiersToLookup[i]].accounts; - for (uint256 matchIndex = 0; matchIndex < matches[i]; matchIndex = matchIndex.add(1)) { - addresses[currentIndex] = getAccounts().getWalletAddress(addrs[matchIndex]); - completed[currentIndex] = identifiers[identifiersToLookup[i]] - .attestations[addrs[matchIndex]] - .completed; - total[currentIndex] = identifiers[identifiersToLookup[i]].attestations[addrs[matchIndex]] - .requested; - currentIndex = currentIndex.add(1); - } - } - - return (matches, addresses, completed, total); - } - - /** - * @notice Returns the state of a specific attestation. - * @param identifier Hash of the identifier. - * @param account Address of the account. - * @param issuer Address of the issuer. - * @return status Status of the attestation. - * @return block Block number of request/completion the attestation. - * @return address Address of the token with which this attestation request was paid for. - */ - function getAttestationState(bytes32 identifier, address account, address issuer) - external - view - returns (uint8, uint32, address) - { - Attestation storage attestation = identifiers[identifier].attestations[account] - .issuedAttestations[issuer]; - return ( - uint8(attestation.status), - attestation.blockNumber, - attestation.attestationRequestFeeToken - ); - - } - - /** - * @notice Returns the state of all attestations that are completable - * @param identifier Hash of the identifier. - * @param account Address of the account. - * @return Block number of request/completion the attestation. - * @return Address of the issuer. - * @return The length of each metadataURL string for each issuer. - * @return All strings concatenated. - */ - function getCompletableAttestations(bytes32 identifier, address account) - external - view - returns (uint32[] memory, address[] memory, uint256[] memory, bytes memory) - { - AttestedAddress storage state = identifiers[identifier].attestations[account]; - address[] storage issuers = state.selectedIssuers; - - uint256 num = 0; - for (uint256 i = 0; i < issuers.length; i = i.add(1)) { - if (isAttestationCompletable(state.issuedAttestations[issuers[i]])) { - num = num.add(1); - } - } - - uint32[] memory blockNumbers = new uint32[](num); - address[] memory completableIssuers = new address[](num); - - uint256 pointer = 0; - for (uint256 i = 0; i < issuers.length; i = i.add(1)) { - if (isAttestationCompletable(state.issuedAttestations[issuers[i]])) { - blockNumbers[pointer] = state.issuedAttestations[issuers[i]].blockNumber; - completableIssuers[pointer] = issuers[i]; - pointer = pointer.add(1); - } - } - - uint256[] memory stringLengths; - bytes memory stringData; - (stringLengths, stringData) = getAccounts().batchGetMetadataURL(completableIssuers); - return (blockNumbers, completableIssuers, stringLengths, stringData); - } - - /** - * @notice Returns the fee set for a particular token. - * @param token Address of the attestationRequestFeeToken. - * @return The fee. - */ - function getAttestationRequestFee(address token) external view returns (uint256) { - return attestationRequestFees[token]; - } - - /** - * @notice Updates the fee for a particular token. - * @param token The address of the attestationRequestFeeToken. - * @param fee The fee in 'token' that is required for each attestation. - */ - function setAttestationRequestFee(address token, uint256 fee) public onlyOwner { - require(fee > 0, "You have to specify a fee greater than 0"); - attestationRequestFees[token] = fee; - emit AttestationRequestFeeSet(token, fee); - } - - /** - * @notice Updates 'attestationExpiryBlocks'. - * @param _attestationExpiryBlocks The new limit on blocks allowed to come between requesting - * an attestation and completing it. - */ - function setAttestationExpiryBlocks(uint256 _attestationExpiryBlocks) public onlyOwner { - require(_attestationExpiryBlocks > 0, "attestationExpiryBlocks has to be greater than 0"); - attestationExpiryBlocks = _attestationExpiryBlocks; - emit AttestationExpiryBlocksSet(_attestationExpiryBlocks); - } - - /** - * @notice Updates 'selectIssuersWaitBlocks'. - * @param _selectIssuersWaitBlocks The wait period in blocks to call selectIssuers on attestation - * requests. - */ - function setSelectIssuersWaitBlocks(uint256 _selectIssuersWaitBlocks) public onlyOwner { - require(_selectIssuersWaitBlocks > 0, "selectIssuersWaitBlocks has to be greater than 0"); - selectIssuersWaitBlocks = _selectIssuersWaitBlocks; - emit SelectIssuersWaitBlocksSet(_selectIssuersWaitBlocks); - } - - /** - * @notice Updates 'maxAttestations'. - * @param _maxAttestations Maximum number of attestations that can be requested. - */ - function setMaxAttestations(uint256 _maxAttestations) public onlyOwner { - require(_maxAttestations > 0, "maxAttestations has to be greater than 0"); - maxAttestations = _maxAttestations; - emit MaxAttestationsSet(_maxAttestations); - } - - /** - * @notice Query 'maxAttestations' - * @return Maximum number of attestations that can be requested. - */ - function getMaxAttestations() external view returns (uint256) { - return maxAttestations; - } - - /** - * @notice Validates the given attestation code. - * @param identifier The hash of the identifier to be attested. - * @param account Address of the account. - * @param v The recovery id of the incoming ECDSA signature. - * @param r Output value r of the ECDSA signature. - * @param s Output value s of the ECDSA signature. - * @return The issuer of the corresponding attestation. - * @dev Throws if there is no matching outstanding attestation request. - * @dev Throws if the attestation window has passed. - */ - function validateAttestationCode( - bytes32 identifier, - address account, - uint8 v, - bytes32 r, - bytes32 s - ) public view returns (address) { - bytes32 codehash = keccak256(abi.encodePacked(identifier, account)); - address signer = Signatures.getSignerOfMessageHash(codehash, v, r, s); - address issuer = getAccounts().attestationSignerToAccount(signer); - - Attestation storage attestation = identifiers[identifier].attestations[account] - .issuedAttestations[issuer]; - - require( - attestation.status == AttestationStatus.Incomplete, - "Attestation code does not match any outstanding attestation" - ); - require(!isAttestationExpired(attestation.blockNumber), "Attestation timed out"); - - return issuer; - } - - function lookupAccountsForIdentifier(bytes32 identifier) - external - view - returns (address[] memory) - { - return identifiers[identifier].accounts; - } - - /** - * @notice Require that a given identifier/address pair has - * requested a specific number of attestations. - * @param identifier Hash of the identifier. - * @param account Address of the account. - * @param expected Number of expected attestations - * @dev It can be used when batching meta-transactions to validate - * attestation are requested as expected in untrusted scenarios - */ - function requireNAttestationsRequested(bytes32 identifier, address account, uint32 expected) - external - view - { - uint256 requested = identifiers[identifier].attestations[account].requested; - require(requested == expected, "requested attestations does not match expected"); - } - - /** - * @notice Helper function for batchGetAttestationStats to calculate the - total number of addresses that have >0 complete attestations for the identifiers. - * @param identifiersToLookup Array of n identifiers. - * @return Array of numbers that indicate the number of matching addresses per identifier. - * @return Array of addresses preallocated for total number of matches. - */ - function batchlookupAccountsForIdentifier(bytes32[] memory identifiersToLookup) - internal - view - returns (uint256[] memory, address[] memory) - { - require(identifiersToLookup.length > 0, "You have to pass at least one identifier"); - uint256 totalAddresses = 0; - uint256[] memory matches = new uint256[](identifiersToLookup.length); - - for (uint256 i = 0; i < identifiersToLookup.length; i = i.add(1)) { - uint256 count = identifiers[identifiersToLookup[i]].accounts.length; - - totalAddresses = totalAddresses.add(count); - matches[i] = count; - } - - return (matches, new address[](totalAddresses)); - } - - function isAttestationExpired(uint32 attestationRequestBlock) internal view returns (bool) { - return block.number >= uint256(attestationRequestBlock).add(attestationExpiryBlocks); - } - - function isAttestationCompletable(Attestation storage attestation) internal view returns (bool) { - return (attestation.status == AttestationStatus.Incomplete && - !isAttestationExpired(attestation.blockNumber)); - } - - function isAttestationRequestSelectable(uint256 attestationRequestBlock) - internal - view - returns (bool) - { - return block.number < attestationRequestBlock.add(getRandom().randomnessBlockRetentionWindow()); - } -} diff --git a/packages/protocol/contracts/identity/Escrow.sol b/packages/protocol/contracts/identity/Escrow.sol deleted file mode 100644 index 818ac4584..000000000 --- a/packages/protocol/contracts/identity/Escrow.sol +++ /dev/null @@ -1,563 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; -import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol"; -import "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol"; - -import "./interfaces/IAttestations.sol"; -import "./interfaces/IFederatedAttestations.sol"; -import "./interfaces/IEscrow.sol"; -import "../common/Initializable.sol"; -import "../common/interfaces/ICeloVersionedContract.sol"; -import "../common/UsingRegistryV2BackwardsCompatible.sol"; -import "../common/Signatures.sol"; -import "../common/libraries/ReentrancyGuard.sol"; - -contract Escrow is - IEscrow, - ICeloVersionedContract, - ReentrancyGuard, - Ownable, - Initializable, - // Maintain storage alignment since Escrow was initially deployed with UsingRegistry.sol - UsingRegistryV2BackwardsCompatible -{ - using SafeMath for uint256; - using SafeERC20 for ERC20; - - event DefaultTrustedIssuerAdded(address indexed trustedIssuer); - event DefaultTrustedIssuerRemoved(address indexed trustedIssuer); - - event Transfer( - address indexed from, - bytes32 indexed identifier, - address indexed token, - uint256 value, - address paymentId, - uint256 minAttestations - ); - - event TrustedIssuersSet(address indexed paymentId, address[] trustedIssuers); - event TrustedIssuersUnset(address indexed paymentId); - - event Withdrawal( - bytes32 indexed identifier, - // Note that in previous versions of Escrow.sol, `to` referenced - // the original sender of the payment - address indexed to, - address indexed token, - uint256 value, - address paymentId - ); - - event Revocation( - bytes32 indexed identifier, - address indexed by, - address indexed token, - uint256 value, - address paymentId - ); - - struct EscrowedPayment { - bytes32 recipientIdentifier; - address sender; - address token; - uint256 value; - uint256 sentIndex; // Location of this payment in sender's list of sent payments. - uint256 receivedIndex; // Location of this payment in receivers's list of received payments. - uint256 timestamp; - uint256 expirySeconds; - uint256 minAttestations; - } - - // Maps unique payment IDs to escrowed payments. - // These payment IDs are the temporary wallet addresses created with the escrowed payments. - mapping(address => EscrowedPayment) public escrowedPayments; - - // Maps receivers' identifiers to a list of received escrowed payment IDs. - mapping(bytes32 => address[]) public receivedPaymentIds; - - // Maps senders' addresses to a list of sent escrowed payment IDs. - mapping(address => address[]) public sentPaymentIds; - - // Maps payment ID to a list of issuers whose attestations will be accepted. - mapping(address => address[]) public trustedIssuersPerPayment; - - // Governable list of trustedIssuers to set for payments by default. - address[] public defaultTrustedIssuers; - - // Based on benchmarking of FederatedAttestations lookup gas consumption - // in the worst case (with a significant amount of buffer). - uint256 public constant MAX_TRUSTED_ISSUERS_PER_PAYMENT = 100; - - /** - * @notice Sets initialized == true on implementation contracts - * @param test Set to true to skip implementation initialization - */ - constructor(bool test) public Initializable(test) {} - - /** - * @notice Returns the storage, major, minor, and patch version of the contract. - * @return Storage version of the contract. - * @return Major version of the contract. - * @return Minor version of the contract. - * @return Patch version of the contract. - */ - function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { - return (1, 2, 0, 0); - } - - /** - * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. - */ - function initialize() external initializer { - _transferOwnership(msg.sender); - } - - /** - * @notice Add an address to the defaultTrustedIssuers list. - * @param trustedIssuer Address of the trustedIssuer to add. - * @dev Throws if trustedIssuer is null or already in defaultTrustedIssuers. - * @dev Throws if defaultTrustedIssuers is already at max allowed length. - */ - function addDefaultTrustedIssuer(address trustedIssuer) external onlyOwner { - require(address(0) != trustedIssuer, "trustedIssuer can't be null"); - require( - defaultTrustedIssuers.length.add(1) <= MAX_TRUSTED_ISSUERS_PER_PAYMENT, - "defaultTrustedIssuers.length can't exceed allowed number of trustedIssuers" - ); - - // Ensure list of trusted issuers is unique - for (uint256 i = 0; i < defaultTrustedIssuers.length; i = i.add(1)) { - require( - defaultTrustedIssuers[i] != trustedIssuer, - "trustedIssuer already in defaultTrustedIssuers" - ); - } - defaultTrustedIssuers.push(trustedIssuer); - emit DefaultTrustedIssuerAdded(trustedIssuer); - } - - /** - * @notice Remove an address from the defaultTrustedIssuers list. - * @param trustedIssuer Address of the trustedIssuer to remove. - * @param index Index of trustedIssuer in defaultTrustedIssuers. - * @dev Throws if trustedIssuer is not in defaultTrustedIssuers at index. - */ - function removeDefaultTrustedIssuer(address trustedIssuer, uint256 index) external onlyOwner { - uint256 numDefaultTrustedIssuers = defaultTrustedIssuers.length; - require(index < numDefaultTrustedIssuers, "index is invalid"); - require( - defaultTrustedIssuers[index] == trustedIssuer, - "trustedIssuer does not match address found at defaultTrustedIssuers[index]" - ); - if (index != numDefaultTrustedIssuers - 1) { - // Swap last index with index-to-remove - defaultTrustedIssuers[index] = defaultTrustedIssuers[numDefaultTrustedIssuers - 1]; - } - defaultTrustedIssuers.pop(); - emit DefaultTrustedIssuerRemoved(trustedIssuer); - } - - /** - * @notice Transfer tokens to a specific user. Supports both identity with privacy (an empty - * identifier and 0 minAttestations) and without (with identifier and minAttestations). - * Sets trustedIssuers to the issuers listed in `defaultTrustedIssuers`. - * (To override this and set custom trusted issuers, use `transferWithTrustedIssuers`.) - * @param identifier The hashed identifier of a user to transfer to. - * @param token The token to be transferred. - * @param value The amount to be transferred. - * @param expirySeconds The number of seconds before the sender can revoke the payment. - * @param paymentId The address of the temporary wallet associated with this payment. Users must - * prove ownership of the corresponding private key to withdraw from escrow. - * @param minAttestations The min number of attestations required to withdraw the payment. - * @return True if transfer succeeded. - * @dev Throws if 'token' or 'value' is 0. - * @dev Throws if identifier is null and minAttestations > 0. - * @dev If minAttestations is 0, trustedIssuers will be set to empty list. - * @dev msg.sender needs to have already approved this contract to transfer - */ - // solhint-disable-next-line no-simple-event-func-name - function transfer( - bytes32 identifier, - address token, - uint256 value, - uint256 expirySeconds, - address paymentId, - uint256 minAttestations - ) external nonReentrant returns (bool) { - address[] memory trustedIssuers; - // If minAttestations == 0, trustedIssuers should remain empty - if (minAttestations > 0) { - trustedIssuers = defaultTrustedIssuers; - } - return - _transfer( - identifier, - token, - value, - expirySeconds, - paymentId, - minAttestations, - trustedIssuers - ); - } - - /** - * @notice Transfer tokens to a specific user. Supports both identity with privacy (an empty - * identifier and 0 minAttestations) and without (with identifier - * and attestations completed by trustedIssuers). - * @param identifier The hashed identifier of a user to transfer to. - * @param token The token to be transferred. - * @param value The amount to be transferred. - * @param expirySeconds The number of seconds before the sender can revoke the payment. - * @param paymentId The address of the temporary wallet associated with this payment. Users must - * prove ownership of the corresponding private key to withdraw from escrow. - * @param minAttestations The min number of attestations required to withdraw the payment. - * @param trustedIssuers Array of issuers whose attestations in FederatedAttestations.sol - * will be accepted to prove ownership over an identifier. - * @return True if transfer succeeded. - * @dev Throws if 'token' or 'value' is 0. - * @dev Throws if identifier is null and minAttestations > 0. - * @dev Throws if minAttestations == 0 but trustedIssuers are provided. - * @dev msg.sender needs to have already approved this contract to transfer. - */ - function transferWithTrustedIssuers( - bytes32 identifier, - address token, - uint256 value, - uint256 expirySeconds, - address paymentId, - uint256 minAttestations, - address[] calldata trustedIssuers - ) external nonReentrant returns (bool) { - return - _transfer( - identifier, - token, - value, - expirySeconds, - paymentId, - minAttestations, - trustedIssuers - ); - } - - /** - * @notice Withdraws tokens for a verified user. - * @param paymentId The ID for the EscrowedPayment struct that contains all relevant information. - * @param v The recovery id of the incoming ECDSA signature. - * @param r Output value r of the ECDSA signature. - * @param s Output value s of the ECDSA signature. - * @return True if withdraw succeeded. - * @dev Throws if 'token' or 'value' is 0. - * @dev Throws if msg.sender does not prove ownership of the withdraw key. - */ - function withdraw(address paymentId, uint8 v, bytes32 r, bytes32 s) - external - nonReentrant - returns (bool) - { - address signer = Signatures.getSignerOfAddress(msg.sender, v, r, s); - require(signer == paymentId, "Failed to prove ownership of the withdraw key"); - EscrowedPayment memory payment = escrowedPayments[paymentId]; - require(payment.token != address(0) && payment.value > 0, "Invalid withdraw value."); - - // Due to an old bug, there may exist payments with no identifier and minAttestations > 0 - // So ensure that these fail the attestations check, as they previously would have - if (payment.minAttestations > 0) { - bool passedCheck = false; - address[] memory trustedIssuers = trustedIssuersPerPayment[paymentId]; - address attestationsAddress = registryContract.getAddressForOrDie(ATTESTATIONS_REGISTRY_ID); - - if (trustedIssuers.length > 0) { - passedCheck = - hasCompletedV1AttestationsAsTrustedIssuer( - attestationsAddress, - payment.recipientIdentifier, - msg.sender, - payment.minAttestations, - trustedIssuers - ) || - hasCompletedV2Attestations(payment.recipientIdentifier, msg.sender, trustedIssuers); - } else { - // This is for backwards compatibility, not default/fallback behavior - passedCheck = hasCompletedV1Attestations( - attestationsAddress, - payment.recipientIdentifier, - msg.sender, - payment.minAttestations - ); - } - require( - passedCheck, - "This account does not have the required attestations to withdraw this payment." - ); - } - - deletePayment(paymentId); - - ERC20(payment.token).safeTransfer(msg.sender, payment.value); - - emit Withdrawal( - payment.recipientIdentifier, - msg.sender, - payment.token, - payment.value, - paymentId - ); - - return true; - } - - /** - * @notice Revokes tokens for a sender who is redeeming a payment after it has expired. - * @param paymentId The ID for the EscrowedPayment struct that contains all relevant information. - * @dev Throws if 'token' or 'value' is 0. - * @dev Throws if msg.sender is not the sender of payment. - * @dev Throws if redeem time hasn't been reached yet. - */ - function revoke(address paymentId) external nonReentrant returns (bool) { - EscrowedPayment memory payment = escrowedPayments[paymentId]; - require(payment.sender == msg.sender, "Only sender of payment can attempt to revoke payment."); - require( - now >= (payment.timestamp.add(payment.expirySeconds)), - "Transaction not redeemable for sender yet." - ); - - deletePayment(paymentId); - - ERC20(payment.token).safeTransfer(msg.sender, payment.value); - - emit Revocation( - payment.recipientIdentifier, - payment.sender, - payment.token, - payment.value, - paymentId - ); - - return true; - - } - - /** - * @notice Gets array of all Escrowed Payments received by identifier. - * @param identifier The hash of an identifier of the receiver of the escrowed payment. - * @return An array containing all the IDs of the Escrowed Payments that were received - * by the specified receiver. - */ - function getReceivedPaymentIds(bytes32 identifier) external view returns (address[] memory) { - return receivedPaymentIds[identifier]; - } - - /** - * @notice Gets array of all Escrowed Payment IDs sent by sender. - * @param sender The address of the sender of the escrowed payments. - * @return An array containing all the IDs of the Escrowed Payments that were sent by the - * specified sender. - */ - function getSentPaymentIds(address sender) external view returns (address[] memory) { - return sentPaymentIds[sender]; - } - - /** - * @notice Gets array of all trusted issuers set per paymentId. - * @param paymentId The ID of the payment to get. - * @return An array of addresses of trusted issuers set for an escrowed payment. - */ - function getTrustedIssuersPerPayment(address paymentId) external view returns (address[] memory) { - return trustedIssuersPerPayment[paymentId]; - } - - /** - * @notice Gets trusted issuers set as default for payments by `transfer` function. - * @return An array of addresses of trusted issuers. - */ - function getDefaultTrustedIssuers() public view returns (address[] memory) { - return defaultTrustedIssuers; - } - - /** - * @notice Checks if account has completed minAttestations for identifier in Attestations.sol. - * @param attestationsAddress The address of Attestations.sol. - * @param identifier The hash of an identifier for which to look up attestations. - * @param account The account for which to look up attestations. - * @param minAttestations The minimum number of attestations to have completed. - * @return Whether or not attestations in Attestations.sol - * exceeds minAttestations for (identifier, account). - */ - function hasCompletedV1Attestations( - address attestationsAddress, - bytes32 identifier, - address account, - uint256 minAttestations - ) internal view returns (bool) { - IAttestations attestations = IAttestations(attestationsAddress); - (uint64 completedAttestations, ) = attestations.getAttestationStats(identifier, account); - return (uint256(completedAttestations) >= minAttestations); - } - - /** - * @notice Helper function that checks if one of the trustedIssuers is the old Attestations.sol - * contract and applies the escrow V1 check against minAttestations. - * @param attestationsAddress The address of Attestations.sol. - * @param identifier The hash of an identifier for which to look up attestations. - * @param account The account for which to look up attestations. - * @param minAttestations The minimum number of attestations to have completed. - * @param trustedIssuers The trustedIssuer addresses to search through. - * @return Whether or not a trustedIssuer is Attestations.sol & attestations - * exceed minAttestations for (identifier, account). - */ - function hasCompletedV1AttestationsAsTrustedIssuer( - address attestationsAddress, - bytes32 identifier, - address account, - uint256 minAttestations, - address[] memory trustedIssuers - ) internal view returns (bool) { - for (uint256 i = 0; i < trustedIssuers.length; i = i.add(1)) { - if (trustedIssuers[i] != attestationsAddress) { - continue; - } - // This can be false; one of the several trustedIssuers listed needs to prove attestations - return hasCompletedV1Attestations(attestationsAddress, identifier, account, minAttestations); - } - return false; - } - - /** - * @notice Checks if there are attestations for account <-> identifier from - * any of trustedIssuers in FederatedAttestations.sol. - * @param identifier The hash of an identifier for which to look up attestations. - * @param account The account for which to look up attestations. - * @param trustedIssuers Issuer addresses whose attestations to trust. - * @return Whether or not attestations exist in FederatedAttestations.sol - * for (identifier, account). - */ - function hasCompletedV2Attestations( - bytes32 identifier, - address account, - address[] memory trustedIssuers - ) internal view returns (bool) { - // Check for an attestation from a trusted issuer - IFederatedAttestations federatedAttestations = getFederatedAttestations(); - (, address[] memory accounts, , , ) = federatedAttestations.lookupAttestations( - identifier, - trustedIssuers - ); - // Check if an attestation was found for recipientIdentifier -> account - for (uint256 i = 0; i < accounts.length; i = i.add(1)) { - if (accounts[i] == account) { - return true; - } - } - return false; - } - - /** - * @notice Helper function for `transferWithTrustedIssuers` and `transfer`, to - * enable backwards-compatible function signature for `transfer`, - * and since `transfer` cannot directly call `transferWithTrustedIssuers` - * due to reentrancy guard. - * @param identifier The hashed identifier of a user to transfer to. - * @param token The token to be transferred. - * @param value The amount to be transferred. - * @param expirySeconds The number of seconds before the sender can revoke the payment. - * @param paymentId The address of the temporary wallet associated with this payment. Users must - * prove ownership of the corresponding private key to withdraw from escrow. - * @param minAttestations The min number of attestations required to withdraw the payment. - * @param trustedIssuers Array of issuers whose attestations in FederatedAttestations.sol - * will be accepted to prove ownership over an identifier. - * @return True if transfer succeeded. - * @dev Throws if 'token' or 'value' is 0. - * @dev Throws if identifier is null and minAttestations > 0. - * @dev Throws if minAttestations == 0 but trustedIssuers are provided. - * @dev msg.sender needs to have already approved this contract to transfer. - */ - function _transfer( - bytes32 identifier, - address token, - uint256 value, - uint256 expirySeconds, - address paymentId, - uint256 minAttestations, - address[] memory trustedIssuers - ) private returns (bool) { - require(token != address(0) && value > 0 && expirySeconds > 0, "Invalid transfer inputs."); - require( - !(identifier == 0 && minAttestations > 0), - "Invalid privacy inputs: Can't require attestations if no identifier" - ); - // Withdraw logic with trustedIssuers in FederatedAttestations disregards - // minAttestations, so ensure that this is not set to 0 to prevent confusing behavior - // This also implies: if identifier == 0 => trustedIssuers.length == 0 - require( - !(minAttestations == 0 && trustedIssuers.length > 0), - "trustedIssuers may only be set when attestations are required" - ); - - // Ensure that withdrawal will not fail due to exceeding trustedIssuer limit - // in FederatedAttestations.lookupAttestations - require( - trustedIssuers.length <= MAX_TRUSTED_ISSUERS_PER_PAYMENT, - "Too many trustedIssuers provided" - ); - - IAttestations attestations = getAttestations(); - require( - minAttestations <= attestations.getMaxAttestations(), - "minAttestations larger than limit" - ); - - uint256 sentIndex = sentPaymentIds[msg.sender].push(paymentId).sub(1); - uint256 receivedIndex = receivedPaymentIds[identifier].push(paymentId).sub(1); - - EscrowedPayment storage newPayment = escrowedPayments[paymentId]; - require(newPayment.timestamp == 0, "paymentId already used"); - newPayment.recipientIdentifier = identifier; - newPayment.sender = msg.sender; - newPayment.token = token; - newPayment.value = value; - newPayment.sentIndex = sentIndex; - newPayment.receivedIndex = receivedIndex; - newPayment.timestamp = block.timestamp; - newPayment.expirySeconds = expirySeconds; - newPayment.minAttestations = minAttestations; - - // Avoid unnecessary storage write - if (trustedIssuers.length > 0) { - trustedIssuersPerPayment[paymentId] = trustedIssuers; - } - - ERC20(token).safeTransferFrom(msg.sender, address(this), value); - emit Transfer(msg.sender, identifier, token, value, paymentId, minAttestations); - // Split into a second event for ABI backwards compatibility - emit TrustedIssuersSet(paymentId, trustedIssuers); - return true; - } - - /** - * @notice Deletes the payment from its receiver's and sender's lists of payments, - * and zeroes out all the data in the struct. - * @param paymentId The ID of the payment to be deleted. - */ - function deletePayment(address paymentId) private { - EscrowedPayment storage payment = escrowedPayments[paymentId]; - address[] storage received = receivedPaymentIds[payment.recipientIdentifier]; - address[] storage sent = sentPaymentIds[payment.sender]; - - escrowedPayments[received[received.length - 1]].receivedIndex = payment.receivedIndex; - received[payment.receivedIndex] = received[received.length - 1]; - received.length = received.length.sub(1); - - escrowedPayments[sent[sent.length - 1]].sentIndex = payment.sentIndex; - sent[payment.sentIndex] = sent[sent.length - 1]; - sent.length = sent.length.sub(1); - - delete escrowedPayments[paymentId]; - delete trustedIssuersPerPayment[paymentId]; - emit TrustedIssuersUnset(paymentId); - } -} diff --git a/packages/protocol/contracts/identity/FederatedAttestations.sol b/packages/protocol/contracts/identity/FederatedAttestations.sol deleted file mode 100644 index 2013d2562..000000000 --- a/packages/protocol/contracts/identity/FederatedAttestations.sol +++ /dev/null @@ -1,517 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; -import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; -import "openzeppelin-solidity/contracts/utils/SafeCast.sol"; - -import "./interfaces/IFederatedAttestations.sol"; -import "../common/interfaces/IAccounts.sol"; -import "../common/interfaces/ICeloVersionedContract.sol"; - -import "../common/Initializable.sol"; -import "../common/UsingRegistryV2.sol"; -import "../common/Signatures.sol"; - -/** - * @title Contract mapping identifiers to accounts - */ -contract FederatedAttestations is - IFederatedAttestations, - ICeloVersionedContract, - Ownable, - Initializable, - UsingRegistryV2 -{ - using SafeMath for uint256; - using SafeCast for uint256; - - struct OwnershipAttestation { - address account; - address signer; - uint64 issuedOn; - uint64 publishedOn; - // using uint64 to allow for extra space to add parameters - } - - // Mappings from identifier <-> attestation are separated by issuer, - // *requiring* users to specify issuers when retrieving attestations. - // Maintaining bidirectional mappings (vs. in Attestations.sol) makes it possible - // to perform lookups by identifier or account without indexing event data. - - // identifier -> issuer -> attestations - mapping(bytes32 => mapping(address => OwnershipAttestation[])) public identifierToAttestations; - // account -> issuer -> identifiers - mapping(address => mapping(address => bytes32[])) public addressToIdentifiers; - - // unique attestation hash -> isRevoked - mapping(bytes32 => bool) public revokedAttestations; - - bytes32 public eip712DomainSeparator; - bytes32 public constant EIP712_OWNERSHIP_ATTESTATION_TYPEHASH = keccak256( - abi.encodePacked( - "OwnershipAttestation(bytes32 identifier,address issuer,", - "address account,address signer,uint64 issuedOn)" - ) - ); - - // Changing any of these constraints will require re-benchmarking - // and checking assumptions for batch revocation. - // These can only be modified by releasing a new version of this contract. - uint256 public constant MAX_ATTESTATIONS_PER_IDENTIFIER = 20; - uint256 public constant MAX_IDENTIFIERS_PER_ADDRESS = 20; - - event EIP712DomainSeparatorSet(bytes32 eip712DomainSeparator); - event AttestationRegistered( - bytes32 indexed identifier, - address indexed issuer, - address indexed account, - address signer, - uint64 issuedOn, - uint64 publishedOn - ); - event AttestationRevoked( - bytes32 indexed identifier, - address indexed issuer, - address indexed account, - address signer, - uint64 issuedOn, - uint64 publishedOn - ); - - /** - * @notice Sets initialized == true on implementation contracts - * @param test Set to true to skip implementation initialization - */ - constructor(bool test) public Initializable(test) {} - - /** - * @notice Returns the storage, major, minor, and patch version of the contract. - * @return The storage, major, minor, and patch version of the contract. - */ - function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { - return (1, 1, 0, 0); - } - - /** - * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. - */ - function initialize() external initializer { - _transferOwnership(msg.sender); - setEip712DomainSeparator(); - } - - /** - * @notice Registers an attestation directly from the issuer - * @param identifier Hash of the identifier to be attested - * @param account Address of the account being mapped to the identifier - * @param issuedOn Time at which the issuer issued the attestation in Unix time - * @dev Attestation signer and issuer in storage is set to msg.sender - * @dev Throws if an attestation with the same (identifier, issuer, account) already exists - */ - function registerAttestationAsIssuer(bytes32 identifier, address account, uint64 issuedOn) - external - { - _registerAttestation(identifier, msg.sender, account, msg.sender, issuedOn); - } - - /** - * @notice Registers an attestation with a valid signature - * @param identifier Hash of the identifier to be attested - * @param issuer Address of the attestation issuer - * @param account Address of the account being mapped to the identifier - * @param issuedOn Time at which the issuer issued the attestation in Unix time - * @param signer Address of the signer of the attestation - * @param v The recovery id of the incoming ECDSA signature - * @param r Output value r of the ECDSA signature - * @param s Output value s of the ECDSA signature - * @dev Throws if an attestation with the same (identifier, issuer, account) already exists - */ - function registerAttestation( - bytes32 identifier, - address issuer, - address account, - address signer, - uint64 issuedOn, - uint8 v, - bytes32 r, - bytes32 s - ) external { - validateAttestationSig(identifier, issuer, account, signer, issuedOn, v, r, s); - _registerAttestation(identifier, issuer, account, signer, issuedOn); - } - - /** - * @notice Revokes an attestation - * @param identifier Hash of the identifier to be revoked - * @param issuer Address of the attestation issuer - * @param account Address of the account mapped to the identifier - * @dev Throws if sender is not the issuer, signer, or account - */ - function revokeAttestation(bytes32 identifier, address issuer, address account) external { - require( - account == msg.sender || - // Minor gas optimization to prevent storage lookup in Accounts.sol if issuer == msg.sender - issuer == msg.sender || - getAccounts().attestationSignerToAccount(msg.sender) == issuer, - "Sender does not have permission to revoke this attestation" - ); - _revokeAttestation(identifier, issuer, account); - } - - /** - * @notice Revokes attestations [identifiers <-> accounts] from issuer - * @param issuer Address of the issuer of all attestations to be revoked - * @param identifiers Hash of the identifiers - * @param accounts Addresses of the accounts mapped to the identifiers - * at the same indices - * @dev Throws if the number of identifiers and accounts is not the same - * @dev Throws if sender is not the issuer or currently registered signer of issuer - * @dev Throws if an attestation is not found for identifiers[i] <-> accounts[i] - */ - function batchRevokeAttestations( - address issuer, - bytes32[] calldata identifiers, - address[] calldata accounts - ) external { - require(identifiers.length == accounts.length, "Unequal number of identifiers and accounts"); - require( - issuer == msg.sender || getAccounts().attestationSignerToAccount(msg.sender) == issuer, - "Sender does not have permission to revoke attestations from this issuer" - ); - - for (uint256 i = 0; i < identifiers.length; i = i.add(1)) { - _revokeAttestation(identifiers[i], issuer, accounts[i]); - } - } - - /** - * @notice Returns info about attestations for `identifier` produced by - * signers of `trustedIssuers` - * @param identifier Hash of the identifier - * @param trustedIssuers Array of n issuers whose attestations will be included - * @return countsPerIssuer Array of number of attestations returned per issuer - * For m (== sum([0])) found attestations: - * @return accounts Array of m accounts - * @return signers Array of m signers - * @return issuedOns Array of m issuedOns - * @return publishedOns Array of m publishedOns - * @dev Adds attestation info to the arrays in order of provided trustedIssuers - * @dev Expectation that only one attestation exists per (identifier, issuer, account) - */ - function lookupAttestations(bytes32 identifier, address[] calldata trustedIssuers) - external - view - returns ( - uint256[] memory countsPerIssuer, - address[] memory accounts, - address[] memory signers, - uint64[] memory issuedOns, - uint64[] memory publishedOns - ) - { - uint256 totalAttestations; - (totalAttestations, countsPerIssuer) = getNumAttestations(identifier, trustedIssuers); - - accounts = new address[](totalAttestations); - signers = new address[](totalAttestations); - issuedOns = new uint64[](totalAttestations); - publishedOns = new uint64[](totalAttestations); - - totalAttestations = 0; - OwnershipAttestation[] memory attestationsPerIssuer; - - for (uint256 i = 0; i < trustedIssuers.length; i = i.add(1)) { - attestationsPerIssuer = identifierToAttestations[identifier][trustedIssuers[i]]; - for (uint256 j = 0; j < attestationsPerIssuer.length; j = j.add(1)) { - accounts[totalAttestations] = attestationsPerIssuer[j].account; - signers[totalAttestations] = attestationsPerIssuer[j].signer; - issuedOns[totalAttestations] = attestationsPerIssuer[j].issuedOn; - publishedOns[totalAttestations] = attestationsPerIssuer[j].publishedOn; - totalAttestations = totalAttestations.add(1); - } - } - return (countsPerIssuer, accounts, signers, issuedOns, publishedOns); - } - - /** - * @notice Returns identifiers mapped to `account` by signers of `trustedIssuers` - * @param account Address of the account - * @param trustedIssuers Array of n issuers whose identifier mappings will be used - * @return countsPerIssuer Array of number of identifiers returned per issuer - * @return identifiers Array (length == sum([0])) of identifiers - * @dev Adds identifier info to the arrays in order of provided trustedIssuers - * @dev Expectation that only one attestation exists per (identifier, issuer, account) - */ - function lookupIdentifiers(address account, address[] calldata trustedIssuers) - external - view - returns (uint256[] memory countsPerIssuer, bytes32[] memory identifiers) - { - uint256 totalIdentifiers; - (totalIdentifiers, countsPerIssuer) = getNumIdentifiers(account, trustedIssuers); - - identifiers = new bytes32[](totalIdentifiers); - bytes32[] memory identifiersPerIssuer; - - uint256 currIndex = 0; - - for (uint256 i = 0; i < trustedIssuers.length; i = i.add(1)) { - identifiersPerIssuer = addressToIdentifiers[account][trustedIssuers[i]]; - for (uint256 j = 0; j < identifiersPerIssuer.length; j = j.add(1)) { - identifiers[currIndex] = identifiersPerIssuer[j]; - currIndex = currIndex.add(1); - } - } - return (countsPerIssuer, identifiers); - } - - /** - * @notice Validates the given attestation and signature - * @param identifier Hash of the identifier to be attested - * @param issuer Address of the attestation issuer - * @param account Address of the account being mapped to the identifier - * @param issuedOn Time at which the issuer issued the attestation in Unix time - * @param signer Address of the signer of the attestation - * @param v The recovery id of the incoming ECDSA signature - * @param r Output value r of the ECDSA signature - * @param s Output value s of the ECDSA signature - * @dev Throws if attestation has been revoked - * @dev Throws if signer is not an authorized AttestationSigner of the issuer - */ - function validateAttestationSig( - bytes32 identifier, - address issuer, - address account, - address signer, - uint64 issuedOn, - uint8 v, - bytes32 r, - bytes32 s - ) public view { - // attestationSignerToAccount instead of isSigner allows the issuer to act as its own signer - require( - getAccounts().attestationSignerToAccount(signer) == issuer, - "Signer is not a currently authorized AttestationSigner for the issuer" - ); - bytes32 structHash = getUniqueAttestationHash(identifier, issuer, account, signer, issuedOn); - address guessedSigner = Signatures.getSignerOfTypedDataHash( - eip712DomainSeparator, - structHash, - v, - r, - s - ); - require(guessedSigner == signer, "Signature is invalid"); - } - - function getUniqueAttestationHash( - bytes32 identifier, - address issuer, - address account, - address signer, - uint64 issuedOn - ) public pure returns (bytes32) { - return - keccak256( - abi.encode( - EIP712_OWNERSHIP_ATTESTATION_TYPEHASH, - identifier, - issuer, - account, - signer, - issuedOn - ) - ); - } - - /** - * @notice Sets the EIP712 domain separator for the Celo FederatedAttestations abstraction. - */ - function setEip712DomainSeparator() internal { - uint256 chainId; - assembly { - chainId := chainid - } - - eip712DomainSeparator = keccak256( - abi.encode( - keccak256( - "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" - ), - keccak256(bytes("FederatedAttestations")), - keccak256("1.0"), - chainId, - address(this) - ) - ); - emit EIP712DomainSeparatorSet(eip712DomainSeparator); - } - - /** - * @notice Helper function for lookupAttestations to calculate the - total number of attestations completed for an identifier - by each trusted issuer - * @param identifier Hash of the identifier - * @param trustedIssuers Array of n issuers whose attestations will be included - * @return totalAttestations Sum total of attestations found - * @return countsPerIssuer Array of number of attestations found per issuer - */ - function getNumAttestations(bytes32 identifier, address[] memory trustedIssuers) - internal - view - returns (uint256 totalAttestations, uint256[] memory countsPerIssuer) - { - totalAttestations = 0; - uint256 numAttestationsForIssuer; - countsPerIssuer = new uint256[](trustedIssuers.length); - - for (uint256 i = 0; i < trustedIssuers.length; i = i.add(1)) { - numAttestationsForIssuer = identifierToAttestations[identifier][trustedIssuers[i]].length; - totalAttestations = totalAttestations.add(numAttestationsForIssuer); - countsPerIssuer[i] = numAttestationsForIssuer; - } - return (totalAttestations, countsPerIssuer); - } - - /** - * @notice Helper function for lookupIdentifiers to calculate the - total number of identifiers completed for an identifier - by each trusted issuer - * @param account Address of the account - * @param trustedIssuers Array of n issuers whose identifiers will be included - * @return totalIdentifiers Sum total of identifiers found - * @return countsPerIssuer Array of number of identifiers found per issuer - */ - function getNumIdentifiers(address account, address[] memory trustedIssuers) - internal - view - returns (uint256 totalIdentifiers, uint256[] memory countsPerIssuer) - { - totalIdentifiers = 0; - uint256 numIdentifiersForIssuer; - countsPerIssuer = new uint256[](trustedIssuers.length); - - for (uint256 i = 0; i < trustedIssuers.length; i = i.add(1)) { - numIdentifiersForIssuer = addressToIdentifiers[account][trustedIssuers[i]].length; - totalIdentifiers = totalIdentifiers.add(numIdentifiersForIssuer); - countsPerIssuer[i] = numIdentifiersForIssuer; - } - return (totalIdentifiers, countsPerIssuer); - } - - /** - * @notice Registers an attestation - * @param identifier Hash of the identifier to be attested - * @param issuer Address of the attestation issuer - * @param account Address of the account being mapped to the identifier - * @param issuedOn Time at which the issuer issued the attestation in Unix time - * @param signer Address of the signer of the attestation - */ - function _registerAttestation( - bytes32 identifier, - address issuer, - address account, - address signer, - uint64 issuedOn - ) private { - require( - !revokedAttestations[getUniqueAttestationHash(identifier, issuer, account, signer, issuedOn)], - "Attestation has been revoked" - ); - uint256 numExistingAttestations = identifierToAttestations[identifier][issuer].length; - require( - numExistingAttestations.add(1) <= MAX_ATTESTATIONS_PER_IDENTIFIER, - "Max attestations already registered for identifier" - ); - require( - addressToIdentifiers[account][issuer].length.add(1) <= MAX_IDENTIFIERS_PER_ADDRESS, - "Max identifiers already registered for account" - ); - - for (uint256 i = 0; i < numExistingAttestations; i = i.add(1)) { - // This enforces only one attestation to be uploaded - // for a given set of (identifier, issuer, account) - // Editing/upgrading an attestation requires that it be revoked before a new one is registered - require( - identifierToAttestations[identifier][issuer][i].account != account, - "Attestation for this account already exists" - ); - } - uint64 publishedOn = uint64(block.timestamp); - OwnershipAttestation memory attestation = OwnershipAttestation( - account, - signer, - issuedOn, - publishedOn - ); - identifierToAttestations[identifier][issuer].push(attestation); - addressToIdentifiers[account][issuer].push(identifier); - emit AttestationRegistered(identifier, issuer, account, signer, issuedOn, publishedOn); - } - - /** - * @notice Revokes an attestation: - * helper function for revokeAttestation and batchRevokeAttestations - * @param identifier Hash of the identifier to be revoked - * @param issuer Address of the attestation issuer - * @param account Address of the account mapped to the identifier - * @dev Reverts if attestation is not found mapping identifier <-> account - */ - function _revokeAttestation(bytes32 identifier, address issuer, address account) private { - OwnershipAttestation[] storage attestations = identifierToAttestations[identifier][issuer]; - uint256 lenAttestations = attestations.length; - for (uint256 i = 0; i < lenAttestations; i = i.add(1)) { - if (attestations[i].account != account) { - continue; - } - - OwnershipAttestation memory attestation = attestations[i]; - // This is meant to delete the attestations in the array - // and then move the last element in the array to that empty spot, - // to avoid having empty elements in the array - if (i != lenAttestations - 1) { - attestations[i] = attestations[lenAttestations - 1]; - } - attestations.pop(); - - bool deletedIdentifier = false; - bytes32[] storage identifiers = addressToIdentifiers[account][issuer]; - uint256 lenIdentifiers = identifiers.length; - - for (uint256 j = 0; j < lenIdentifiers; j = j.add(1)) { - if (identifiers[j] != identifier) { - continue; - } - if (j != lenIdentifiers - 1) { - identifiers[j] = identifiers[lenIdentifiers - 1]; - } - identifiers.pop(); - deletedIdentifier = true; - break; - } - // Should never be false - both mappings should always be updated in unison - assert(deletedIdentifier); - - bytes32 attestationHash = getUniqueAttestationHash( - identifier, - issuer, - account, - attestation.signer, - attestation.issuedOn - ); - revokedAttestations[attestationHash] = true; - - emit AttestationRevoked( - identifier, - issuer, - account, - attestation.signer, - attestation.issuedOn, - attestation.publishedOn - ); - return; - } - revert("Attestation to be revoked does not exist"); - } -} diff --git a/packages/protocol/contracts/identity/IdentityProxy.sol b/packages/protocol/contracts/identity/IdentityProxy.sol deleted file mode 100644 index 5c6dbfbda..000000000 --- a/packages/protocol/contracts/identity/IdentityProxy.sol +++ /dev/null @@ -1,33 +0,0 @@ -pragma solidity ^0.5.13; - -import "../common/ExternalCall.sol"; - -contract IdentityProxy { - address public deployer; - - constructor() public { - deployer = msg.sender; - } - - modifier onlyDeployer() { - require(msg.sender == deployer, "Only callable by original deployer"); - _; - } - - /** - * @notice Performs an arbitrary call. - * @param destination The address to call. - * @param data The calldata to send with the call. - * @dev This can only be called by the deployer of this contract, presumably - * the IdentityProxyHub after it checks the identity heuristic. - * @return The return value of the external call. - */ - function makeCall(address destination, bytes calldata data) - external - payable - onlyDeployer - returns (bytes memory) - { - return ExternalCall.execute(destination, msg.value, data); - } -} diff --git a/packages/protocol/contracts/identity/IdentityProxyHub.sol b/packages/protocol/contracts/identity/IdentityProxyHub.sol deleted file mode 100644 index 4525e3385..000000000 --- a/packages/protocol/contracts/identity/IdentityProxyHub.sol +++ /dev/null @@ -1,122 +0,0 @@ -pragma solidity ^0.5.13; - -import "../common/Create2.sol"; -import "../common/interfaces/ICeloVersionedContract.sol"; -import "../common/UsingRegistry.sol"; -import "./IdentityProxy.sol"; - -contract IdentityProxyHub is UsingRegistry, ICeloVersionedContract { - bytes32 public constant identityProxyCodeHash = keccak256( - // solhint-disable-next-line indent - abi.encodePacked(type(IdentityProxy).creationCode) - ); - - /** - * @notice Returns the storage, major, minor, and patch version of the contract. - * @return Storage version of the contract. - * @return Major version of the contract. - * @return Minor version of the contract. - * @return Patch version of the contract. - */ - function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { - return (1, 0, 0, 1); - } - - /** - * @notice Returns the IdentityProxy address corresponding to the identifier. - * @param identifier The identifier whose proxy address is computed. - * @return The identifier's IdentityProxy address. - * @dev This function will return a correct address whether or not the - * corresponding IdentityProxy has been deployed. IdentityProxies are deployed - * using CREATE2 and this computes a CREATE2 address. - */ - function getIdentityProxy(bytes32 identifier) public view returns (IdentityProxy) { - return IdentityProxy(Create2.computeAddress(address(this), identifier, identityProxyCodeHash)); - } - - /** - * @notice Returns the IdentityProxy address corresponding to the identifier, - * deploying an IdentityProxy if one hasn't already been deployed for this - * identifier. - * @param identifier The identifier whose proxy address is returned. - * @return The identifier's IdentityProxy address. - */ - function getOrDeployIdentityProxy(bytes32 identifier) public returns (IdentityProxy) { - IdentityProxy identityProxy = getIdentityProxy(identifier); - uint256 codeSize; - assembly { - codeSize := extcodesize(identityProxy) - } - if (codeSize == 0) { - deployIdentityProxy(identifier); - } - - return identityProxy; - } - - /** - * @notice Returns true if the given address is the likely owner of the given - * identifier. - * @param addr The address to check. - * @param identifier The identifier to check. - * @return True if the given address is the likely owner of the given - * identifier, false otherwise. - * @dev Heuristic for ownership checks that the given account: - * 1. Has at least 3 completed attestations on the given identifier. - * 2. Completed strictly more than half of requested attestations. - * 3. Has at least as many completed attestations as any other account. - */ - function passesIdentityHeuristic(address addr, bytes32 identifier) public view returns (bool) { - IAttestations attestations = getAttestations(); - (uint32 completed, uint32 requested) = attestations.getAttestationStats(identifier, addr); - - // 1. Check that the account has at least 3 completed attestations on the given identifier. - bool hasEnoughCompletions = completed >= 3; - - // 2. Check that the account Completed strictly more than half of requested attestations. - bool completedOverHalfRequests = false; - if (completed > 0) { - completedOverHalfRequests = requested / completed < 2; - } - - // 3. Check that the account has at least as many completed attestations as any other account. - bool hasMostCompletions = true; - address[] memory addresses = attestations.lookupAccountsForIdentifier(identifier); - for (uint256 i = 0; i < addresses.length; i++) { - address otherAddr = addresses[i]; - if (otherAddr != addr) { - (uint32 otherCompleted, uint32 _requested) = attestations.getAttestationStats( - identifier, - otherAddr - ); - hasMostCompletions = hasMostCompletions && otherCompleted <= completed; - } - } - - // Return true if the account passed all three checks above. - // Note: We do not return early on failures as we are optimizing for the passing case. - return hasEnoughCompletions && completedOverHalfRequests && hasMostCompletions; - } - - /** - * @notice Performs an arbitrary call through the identifier's IdentityProxy, - * assuming msg.sender passes the identity heuristic. - * @param identifier The identifier whose IdentityProxy to call through. - * @param destination The address the IdentityProxy should call. - * @param data The calldata the IdentityProxy should send with the call. - * @return The return value of the external call. - */ - function makeCall(bytes32 identifier, address destination, bytes calldata data) - external - payable - returns (bytes memory) - { - require(passesIdentityHeuristic(msg.sender, identifier), "does not pass identity heuristic"); - return getOrDeployIdentityProxy(identifier).makeCall.value(msg.value)(destination, data); - } - - function deployIdentityProxy(bytes32 identifier) internal returns (IdentityProxy) { - // solhint-disable-next-line indent - return IdentityProxy(Create2.deploy(identifier, type(IdentityProxy).creationCode)); - } -} diff --git a/packages/protocol/contracts/identity/OdisPayments.sol b/packages/protocol/contracts/identity/OdisPayments.sol deleted file mode 100644 index 33caf6783..000000000 --- a/packages/protocol/contracts/identity/OdisPayments.sol +++ /dev/null @@ -1,75 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; -import "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol"; -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./interfaces/IOdisPayments.sol"; -import "../common/interfaces/ICeloVersionedContract.sol"; - -import "../common/Initializable.sol"; -import "../common/UsingRegistryV2.sol"; -import "../common/libraries/ReentrancyGuard.sol"; - -/** - * @title Stores balance to be used for ODIS quota calculation. - */ -contract OdisPayments is - IOdisPayments, - ICeloVersionedContract, - ReentrancyGuard, - Ownable, - Initializable, - UsingRegistryV2 -{ - using SafeMath for uint256; - using SafeERC20 for IERC20; - - event PaymentMade(address indexed account, uint256 valueInCUSD); - - // Store amount sent (all time) from account to this contract. - // Values in totalPaidCUSD should only ever be incremented, since ODIS relies - // on all-time paid balance to compute every quota. - mapping(address => uint256) public totalPaidCUSD; - - /** - * @notice Sets initialized == true on implementation contracts. - * @param test Set to true to skip implementation initialization. - */ - constructor(bool test) public Initializable(test) {} - - /** - * @notice Returns the storage, major, minor, and patch version of the contract. - * @return Storage version of the contract. - * @return Major version of the contract. - * @return Minor version of the contract. - * @return Patch version of the contract. - */ - function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { - return (1, 1, 0, 0); - } - - /** - * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. - */ - function initialize() external initializer { - _transferOwnership(msg.sender); - } - - /** - * @notice Sends cUSD to this contract to pay for ODIS quota (for queries). - * @param account The account whose balance to increment. - * @param value The amount in cUSD to pay. - * @dev Throws if cUSD transfer fails. - */ - function payInCUSD(address account, uint256 value) external nonReentrant { - IERC20(registryContract.getAddressForOrDie(STABLE_TOKEN_REGISTRY_ID)).safeTransferFrom( - msg.sender, - address(this), - value - ); - totalPaidCUSD[account] = totalPaidCUSD[account].add(value); - emit PaymentMade(account, value); - } -} diff --git a/packages/protocol/contracts/identity/Random.sol b/packages/protocol/contracts/identity/Random.sol deleted file mode 100644 index 87cf5c3d9..000000000 --- a/packages/protocol/contracts/identity/Random.sol +++ /dev/null @@ -1,201 +0,0 @@ -pragma solidity ^0.5.13; - -import "./interfaces/IRandom.sol"; -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "../common/CalledByVm.sol"; -import "../common/Initializable.sol"; -import "../common/UsingPrecompiles.sol"; -import "../common/interfaces/ICeloVersionedContract.sol"; - -/** - * @title Provides randomness for verifier selection - */ -contract Random is - IRandom, - ICeloVersionedContract, - Ownable, - Initializable, - UsingPrecompiles, - CalledByVm -{ - using SafeMath for uint256; - - /* Stores most recent commitment per address */ - mapping(address => bytes32) public commitments; - - uint256 public randomnessBlockRetentionWindow; - - mapping(uint256 => bytes32) private history; - uint256 private historyFirst; - uint256 private historySize; - uint256 private lastEpochBlock; - - event RandomnessBlockRetentionWindowSet(uint256 value); - - /** - * @notice Returns the storage, major, minor, and patch version of the contract. - * @return Storage version of the contract. - * @return Major version of the contract. - * @return Minor version of the contract. - * @return Patch version of the contract. - */ - function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { - return (1, 1, 1, 0); - } - - /** - * @notice Sets initialized == true on implementation contracts - * @param test Set to true to skip implementation initialization - */ - constructor(bool test) public Initializable(test) {} - - /** - * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. - * @param _randomnessBlockRetentionWindow Number of old random blocks whose randomness - * values can be queried. - */ - function initialize(uint256 _randomnessBlockRetentionWindow) external initializer { - _transferOwnership(msg.sender); - setRandomnessBlockRetentionWindow(_randomnessBlockRetentionWindow); - } - - /** - * @notice Sets the number of old random blocks whose randomness values can be queried. - * @param value Number of old random blocks whose randomness values can be queried. - */ - function setRandomnessBlockRetentionWindow(uint256 value) public onlyOwner { - require(value > 0, "randomnessBlockRetetionWindow cannot be zero"); - randomnessBlockRetentionWindow = value; - emit RandomnessBlockRetentionWindowSet(value); - } - - /** - * @notice Implements step of the randomness protocol. - * @param randomness Bytes that will be added to the entropy pool. - * @param newCommitment The hash of randomness that will be revealed in the future. - * @param proposer Address of the block proposer. - * @dev If the Random contract is pointed to by the Registry, the first transaction in a block - * should be a special transaction to address 0x0 with 64 bytes of data - the concatenated - * `randomness` and `newCommitment`. Before running regular transactions, this function should be - * called. - */ - function revealAndCommit(bytes32 randomness, bytes32 newCommitment, address proposer) - external - onlyVm - { - _revealAndCommit(randomness, newCommitment, proposer); - } - - /** - * @notice Implements step of the randomness protocol. - * @param randomness Bytes that will be added to the entropy pool. - * @param newCommitment The hash of randomness that will be revealed in the future. - * @param proposer Address of the block proposer. - */ - function _revealAndCommit(bytes32 randomness, bytes32 newCommitment, address proposer) internal { - require(newCommitment != computeCommitment(0), "cannot commit zero randomness"); - - // ensure revealed randomness matches previous commitment - if (commitments[proposer] != 0) { - require(randomness != 0, "randomness cannot be zero if there is a previous commitment"); - bytes32 expectedCommitment = computeCommitment(randomness); - require( - expectedCommitment == commitments[proposer], - "commitment didn't match the posted randomness" - ); - } else { - require(randomness == 0, "randomness should be zero if there is no previous commitment"); - } - - // add entropy - uint256 blockNumber = block.number == 0 ? 0 : block.number.sub(1); - addRandomness(block.number, keccak256(abi.encodePacked(history[blockNumber], randomness))); - - commitments[proposer] = newCommitment; - } - - /** - * @notice Add a value to the randomness history. - * @param blockNumber Current block number. - * @param randomness The new randomness added to history. - * @dev The calls to this function should be made so that on the next call, blockNumber will - * be the previous one, incremented by one. - */ - function addRandomness(uint256 blockNumber, bytes32 randomness) internal { - history[blockNumber] = randomness; - if (blockNumber % getEpochSize() == 0) { - if (lastEpochBlock < historyFirst) { - delete history[lastEpochBlock]; - } - lastEpochBlock = blockNumber; - } else { - if (historySize == 0) { - historyFirst = blockNumber; - historySize = 1; - } else if (historySize > randomnessBlockRetentionWindow) { - deleteHistoryIfNotLastEpochBlock(historyFirst); - deleteHistoryIfNotLastEpochBlock(historyFirst.add(1)); - historyFirst = historyFirst.add(2); - historySize = historySize.sub(1); - } else if (historySize == randomnessBlockRetentionWindow) { - deleteHistoryIfNotLastEpochBlock(historyFirst); - historyFirst = historyFirst.add(1); - } else { - // historySize < randomnessBlockRetentionWindow - historySize = historySize.add(1); - } - } - } - - /** - * @notice Compute the commitment hash for a given randomness value. - * @param randomness The value for which the commitment hash is computed. - * @return Commitment parameter. - */ - function computeCommitment(bytes32 randomness) public pure returns (bytes32) { - return keccak256(abi.encodePacked(randomness)); - } - - /** - * @notice Querying the current randomness value. - * @return Returns the current randomness value. - */ - function random() external view returns (bytes32) { - return _getBlockRandomness(block.number, block.number); - } - - /** - * @notice Get randomness values of previous blocks. - * @param blockNumber The number of block whose randomness value we want to know. - * @return The associated randomness value. - */ - function getBlockRandomness(uint256 blockNumber) external view returns (bytes32) { - return _getBlockRandomness(blockNumber, block.number); - } - - /** - * @notice Get randomness values of previous blocks. - * @param blockNumber The number of block whose randomness value we want to know. - * @param cur Number of the current block. - * @return The associated randomness value. - */ - function _getBlockRandomness(uint256 blockNumber, uint256 cur) internal view returns (bytes32) { - require(blockNumber <= cur, "Cannot query randomness of future blocks"); - require( - blockNumber == lastEpochBlock || - (blockNumber > cur.sub(historySize) && - (randomnessBlockRetentionWindow >= cur || - blockNumber > cur.sub(randomnessBlockRetentionWindow))), - "Cannot query randomness older than the stored history" - ); - return history[blockNumber]; - } - - function deleteHistoryIfNotLastEpochBlock(uint256 blockNumber) internal { - if (blockNumber != lastEpochBlock) { - delete history[blockNumber]; - } - } -} diff --git a/packages/protocol/contracts/identity/interfaces/IAttestations.sol b/packages/protocol/contracts/identity/interfaces/IAttestations.sol deleted file mode 100644 index 195e8de3f..000000000 --- a/packages/protocol/contracts/identity/interfaces/IAttestations.sol +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.5.13 <0.9.0; - -interface IAttestations { - function revoke(bytes32, uint256) external; - function withdraw(address) external; - - // view functions - function getUnselectedRequest(bytes32, address) external view returns (uint32, uint32, address); - function getAttestationIssuers(bytes32, address) external view returns (address[] memory); - function getAttestationStats(bytes32, address) external view returns (uint32, uint32); - function batchGetAttestationStats(bytes32[] calldata) - external - view - returns (uint256[] memory, address[] memory, uint64[] memory, uint64[] memory); - function getAttestationState(bytes32, address, address) - external - view - returns (uint8, uint32, address); - function getCompletableAttestations(bytes32, address) - external - view - returns (uint32[] memory, address[] memory, uint256[] memory, bytes memory); - function getAttestationRequestFee(address) external view returns (uint256); - function getMaxAttestations() external view returns (uint256); - function validateAttestationCode(bytes32, address, uint8, bytes32, bytes32) - external - view - returns (address); - function lookupAccountsForIdentifier(bytes32) external view returns (address[] memory); - function requireNAttestationsRequested(bytes32, address, uint32) external view; - - // only owner - function setAttestationRequestFee(address, uint256) external; - function setAttestationExpiryBlocks(uint256) external; - function setSelectIssuersWaitBlocks(uint256) external; - function setMaxAttestations(uint256) external; -} diff --git a/packages/protocol/contracts/identity/interfaces/IEscrow.sol b/packages/protocol/contracts/identity/interfaces/IEscrow.sol deleted file mode 100644 index 965a31d63..000000000 --- a/packages/protocol/contracts/identity/interfaces/IEscrow.sol +++ /dev/null @@ -1,34 +0,0 @@ -pragma solidity ^0.5.13; - -interface IEscrow { - function transfer( - bytes32 identifier, - address token, - uint256 value, - uint256 expirySeconds, - address paymentId, - uint256 minAttestations - ) external returns (bool); - function transferWithTrustedIssuers( - bytes32 identifier, - address token, - uint256 value, - uint256 expirySeconds, - address paymentId, - uint256 minAttestations, - address[] calldata trustedIssuers - ) external returns (bool); - function withdraw(address paymentID, uint8 v, bytes32 r, bytes32 s) external returns (bool); - function revoke(address paymentID) external returns (bool); - - // view functions - function getReceivedPaymentIds(bytes32 identifier) external view returns (address[] memory); - function getSentPaymentIds(address sender) external view returns (address[] memory); - function getTrustedIssuersPerPayment(address paymentId) external view returns (address[] memory); - function getDefaultTrustedIssuers() external view returns (address[] memory); - function MAX_TRUSTED_ISSUERS_PER_PAYMENT() external view returns (uint256); - - // onlyOwner functions - function addDefaultTrustedIssuer(address trustedIssuer) external; - function removeDefaultTrustedIssuer(address trustedIssuer, uint256 index) external; -} diff --git a/packages/protocol/contracts/identity/interfaces/IFederatedAttestations.sol b/packages/protocol/contracts/identity/interfaces/IFederatedAttestations.sol deleted file mode 100644 index 03a645970..000000000 --- a/packages/protocol/contracts/identity/interfaces/IFederatedAttestations.sol +++ /dev/null @@ -1,55 +0,0 @@ -pragma solidity ^0.5.13; - -interface IFederatedAttestations { - function registerAttestationAsIssuer(bytes32 identifier, address account, uint64 issuedOn) - external; - function registerAttestation( - bytes32 identifier, - address issuer, - address account, - address signer, - uint64 issuedOn, - uint8 v, - bytes32 r, - bytes32 s - ) external; - function revokeAttestation(bytes32 identifier, address issuer, address account) external; - function batchRevokeAttestations( - address issuer, - bytes32[] calldata identifiers, - address[] calldata accounts - ) external; - - // view functions - function lookupAttestations(bytes32 identifier, address[] calldata trustedIssuers) - external - view - returns ( - uint256[] memory, - address[] memory, - address[] memory, - uint64[] memory, - uint64[] memory - ); - function lookupIdentifiers(address account, address[] calldata trustedIssuers) - external - view - returns (uint256[] memory, bytes32[] memory); - function validateAttestationSig( - bytes32 identifier, - address issuer, - address account, - address signer, - uint64 issuedOn, - uint8 v, - bytes32 r, - bytes32 s - ) external view; - function getUniqueAttestationHash( - bytes32 identifier, - address issuer, - address account, - address signer, - uint64 issuedOn - ) external pure returns (bytes32); -} diff --git a/packages/protocol/contracts/identity/interfaces/IOdisPayments.sol b/packages/protocol/contracts/identity/interfaces/IOdisPayments.sol deleted file mode 100644 index 98b00d2fc..000000000 --- a/packages/protocol/contracts/identity/interfaces/IOdisPayments.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -interface IOdisPayments { - function payInCUSD(address account, uint256 value) external; - function totalPaidCUSD(address) external view returns (uint256); -} diff --git a/packages/protocol/contracts/identity/interfaces/IRandom.sol b/packages/protocol/contracts/identity/interfaces/IRandom.sol deleted file mode 100644 index c2eb8851e..000000000 --- a/packages/protocol/contracts/identity/interfaces/IRandom.sol +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.5.13 <0.9.0; - -interface IRandom { - function revealAndCommit(bytes32, bytes32, address) external; - function randomnessBlockRetentionWindow() external view returns (uint256); - function random() external view returns (bytes32); - function getBlockRandomness(uint256) external view returns (bytes32); -} diff --git a/packages/protocol/contracts/identity/proxies/AttestationsProxy.sol b/packages/protocol/contracts/identity/proxies/AttestationsProxy.sol deleted file mode 100644 index 0cba1fe42..000000000 --- a/packages/protocol/contracts/identity/proxies/AttestationsProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../../common/Proxy.sol"; - -/* solhint-disable-next-line no-empty-blocks */ -contract AttestationsProxy is Proxy {} diff --git a/packages/protocol/contracts/identity/proxies/EscrowProxy.sol b/packages/protocol/contracts/identity/proxies/EscrowProxy.sol deleted file mode 100644 index e71fcdd42..000000000 --- a/packages/protocol/contracts/identity/proxies/EscrowProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../../common/Proxy.sol"; - -/* solhint-disable-next-line no-empty-blocks */ -contract EscrowProxy is Proxy {} diff --git a/packages/protocol/contracts/identity/proxies/FederatedAttestationsProxy.sol b/packages/protocol/contracts/identity/proxies/FederatedAttestationsProxy.sol deleted file mode 100644 index 6edd4884f..000000000 --- a/packages/protocol/contracts/identity/proxies/FederatedAttestationsProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../../common/Proxy.sol"; - -/* solhint-disable no-empty-blocks */ -contract FederatedAttestationsProxy is Proxy {} diff --git a/packages/protocol/contracts/identity/proxies/OdisPaymentsProxy.sol b/packages/protocol/contracts/identity/proxies/OdisPaymentsProxy.sol deleted file mode 100644 index 9114e1a5f..000000000 --- a/packages/protocol/contracts/identity/proxies/OdisPaymentsProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../../common/Proxy.sol"; - -/* solhint-disable no-empty-blocks */ -contract OdisPaymentsProxy is Proxy {} diff --git a/packages/protocol/contracts/identity/proxies/RandomProxy.sol b/packages/protocol/contracts/identity/proxies/RandomProxy.sol deleted file mode 100644 index 5009245ef..000000000 --- a/packages/protocol/contracts/identity/proxies/RandomProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../../common/Proxy.sol"; - -/* solhint-disable-next-line no-empty-blocks */ -contract RandomProxy is Proxy {} diff --git a/packages/protocol/contracts/identity/test/AttestationsTest.sol b/packages/protocol/contracts/identity/test/AttestationsTest.sol deleted file mode 100644 index f870ac0da..000000000 --- a/packages/protocol/contracts/identity/test/AttestationsTest.sol +++ /dev/null @@ -1,202 +0,0 @@ -pragma solidity ^0.5.13; - -import "../Attestations.sol"; - -/* - * We need a test contract that behaves like the actual Attestations contract, - * but mocks the implementations of the validator set getters. Otherwise we - * couldn't test `request` with the current ganache local testnet. - */ -contract AttestationsTest is Attestations(true) { - address[] private __testValidators; - - function __setValidators(address[] memory validators) public { - __testValidators = validators; - } - - function numberValidatorsInCurrentSet() public view returns (uint256) { - return __testValidators.length; - } - - function validatorSignerAddressFromCurrentSet(uint256 index) public view returns (address) { - return __testValidators[index]; - } - - // some deprecated functions are mocked here to ensure that the tests for - // revoke and withdraw can still run - - /** - * @notice Commit to the attestation request of a hashed identifier. - * @param identifier The hash of the identifier to be attested. - * @param attestationsRequested The number of requested attestations for this request. - * @param attestationRequestFeeToken The address of the token with which the attestation fee will - * be paid. - * @dev Note that if an attestation expires before it is completed, the fee is forfeited. This is - * to prevent folks from attacking validators by requesting attestations that they do not - * complete, and to increase the cost of validators attempting to manipulate the attestations - * protocol. - */ - function request( - bytes32 identifier, - uint256 attestationsRequested, - address attestationRequestFeeToken - ) external nonReentrant { - require( - attestationRequestFees[attestationRequestFeeToken] > 0, - "Invalid attestationRequestFeeToken" - ); - require( - IERC20(attestationRequestFeeToken).transferFrom( - msg.sender, - address(this), - attestationRequestFees[attestationRequestFeeToken].mul(attestationsRequested) - ), - "Transfer of attestation request fees failed" - ); - - require(attestationsRequested > 0, "You have to request at least 1 attestation"); - require(attestationsRequested <= maxAttestations, "Too many attestations requested"); - - IdentifierState storage state = identifiers[identifier]; - - require( - state.unselectedRequests[msg.sender].blockNumber == 0 || - isAttestationExpired(state.unselectedRequests[msg.sender].blockNumber) || - !isAttestationRequestSelectable(state.unselectedRequests[msg.sender].blockNumber), - "There exists an unexpired, unselected attestation request" - ); - - state.unselectedRequests[msg.sender].blockNumber = block.number.toUint32(); - state.unselectedRequests[msg.sender].attestationsRequested = attestationsRequested.toUint32(); - state.unselectedRequests[msg.sender].attestationRequestFeeToken = attestationRequestFeeToken; - - state.attestations[msg.sender].requested = uint256(state.attestations[msg.sender].requested) - .add(attestationsRequested) - .toUint32(); - - emit AttestationsRequested( - identifier, - msg.sender, - attestationsRequested, - attestationRequestFeeToken - ); - } - - /** - * @notice Selects the issuers for the most recent attestation request. - * @param identifier The hash of the identifier to be attested. - */ - function selectIssuers(bytes32 identifier) external { - IdentifierState storage state = identifiers[identifier]; - - require( - state.unselectedRequests[msg.sender].blockNumber > 0, - "No unselected attestation request to select issuers for" - ); - - require( - !isAttestationExpired(state.unselectedRequests[msg.sender].blockNumber), - "The attestation request has expired" - ); - - addIncompleteAttestations(identifier); - delete state.unselectedRequests[msg.sender]; - } - - /** - * @notice Submit the secret message sent by the issuer to complete the attestation request. - * @param identifier The hash of the identifier for this attestation. - * @param v The recovery id of the incoming ECDSA signature. - * @param r Output value r of the ECDSA signature. - * @param s Output value s of the ECDSA signature. - * @dev Throws if there is no matching outstanding attestation request. - * @dev Throws if the attestation window has passed. - */ - function complete(bytes32 identifier, uint8 v, bytes32 r, bytes32 s) external { - address issuer = validateAttestationCode(identifier, msg.sender, v, r, s); - - Attestation storage attestation = identifiers[identifier].attestations[msg.sender] - .issuedAttestations[issuer]; - - address token = attestation.attestationRequestFeeToken; - - // solhint-disable-next-line not-rely-on-time - attestation.blockNumber = block.number.toUint32(); - attestation.status = AttestationStatus.Complete; - delete attestation.attestationRequestFeeToken; - AttestedAddress storage attestedAddress = identifiers[identifier].attestations[msg.sender]; - require( - attestedAddress.completed < attestedAddress.completed + 1, - "SafeMath32 integer overflow" - ); - attestedAddress.completed = attestedAddress.completed + 1; - - pendingWithdrawals[token][issuer] = pendingWithdrawals[token][issuer].add( - attestationRequestFees[token] - ); - - IdentifierState storage state = identifiers[identifier]; - if (identifiers[identifier].attestations[msg.sender].completed == 1) { - state.accounts.push(msg.sender); - } - - emit AttestationCompleted(identifier, msg.sender, issuer); - } - - /** - * @notice Adds additional attestations given the current randomness. - * @param identifier The hash of the identifier to be attested. - */ - function addIncompleteAttestations(bytes32 identifier) internal { - AttestedAddress storage state = identifiers[identifier].attestations[msg.sender]; - UnselectedRequest storage unselectedRequest = identifiers[identifier].unselectedRequests[msg - .sender]; - - bytes32 seed = getRandom().getBlockRandomness( - uint256(unselectedRequest.blockNumber).add(selectIssuersWaitBlocks) - ); - IAccounts accounts = getAccounts(); - uint256 issuersLength = numberValidatorsInCurrentSet(); - uint256[] memory issuers = new uint256[](issuersLength); - for (uint256 i = 0; i < issuersLength; i = i.add(1)) issuers[i] = i; - - require(unselectedRequest.attestationsRequested <= issuersLength, "not enough issuers"); - - uint256 currentIndex = 0; - - // The length of the list (variable issuersLength) is decremented in each round, - // so the loop always terminates - while (currentIndex < unselectedRequest.attestationsRequested) { - require(issuersLength > 0, "not enough issuers"); - seed = keccak256(abi.encodePacked(seed)); - uint256 idx = uint256(seed) % issuersLength; - address signer = validatorSignerAddressFromCurrentSet(issuers[idx]); - address issuer = accounts.signerToAccount(signer); - - Attestation storage attestation = state.issuedAttestations[issuer]; - - if ( - attestation.status == AttestationStatus.None && - accounts.hasAuthorizedAttestationSigner(issuer) - ) { - currentIndex = currentIndex.add(1); - attestation.status = AttestationStatus.Incomplete; - attestation.blockNumber = unselectedRequest.blockNumber; - attestation.attestationRequestFeeToken = unselectedRequest.attestationRequestFeeToken; - state.selectedIssuers.push(issuer); - - emit AttestationIssuerSelected( - identifier, - msg.sender, - issuer, - unselectedRequest.attestationRequestFeeToken - ); - } - - // Remove the validator that was selected from the list, - // by replacing it by the last element in the list - issuersLength = issuersLength.sub(1); - issuers[idx] = issuers[issuersLength]; - } - } -} diff --git a/packages/protocol/contracts/identity/test/IdentityProxyTest.sol b/packages/protocol/contracts/identity/test/IdentityProxyTest.sol deleted file mode 100644 index 85131e496..000000000 --- a/packages/protocol/contracts/identity/test/IdentityProxyTest.sol +++ /dev/null @@ -1,19 +0,0 @@ -pragma solidity ^0.5.13; - -contract IdentityProxyTest { - address public lastAddress; - uint256 public x; - uint256 public amountLastPaid; - - function callMe() external { - lastAddress = msg.sender; - } - - function payMe() external payable { - amountLastPaid = msg.value; - } - - function setX(uint256 _x) external { - x = _x; - } -} diff --git a/packages/protocol/contracts/identity/test/MockAttestations.sol b/packages/protocol/contracts/identity/test/MockAttestations.sol deleted file mode 100644 index 1c93409e7..000000000 --- a/packages/protocol/contracts/identity/test/MockAttestations.sol +++ /dev/null @@ -1,64 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; - -/** - * @title A mock Attestations for testing. - */ -contract MockAttestations { - enum AttestationStatus { None, Incomplete, Complete } - - struct Attestation { - AttestationStatus status; - uint128 time; - } - - struct Attestations { - uint32 completed; - uint32 requested; - address[] issuers; - mapping(address => Attestation) issuedAttestations; - } - - struct IdentifierState { - address[] accounts; - mapping(address => Attestations) attestations; - } - - mapping(bytes32 => IdentifierState) identifiers; - - function complete(bytes32 identifier, uint8, bytes32, bytes32) external { - identifiers[identifier].attestations[msg.sender].completed++; - - if (identifiers[identifier].attestations[msg.sender].completed == 1) { - identifiers[identifier].accounts.push(msg.sender); - } - } - - function request(bytes32 identifier, uint8, bytes32, bytes32) external { - identifiers[identifier].attestations[msg.sender].requested++; - } - - function getMaxAttestations() external pure returns (uint256) { - return 20; - } - - function getAttestationStats(bytes32 identifier, address account) - external - view - returns (uint64, uint64) - { - return ( - identifiers[identifier].attestations[account].completed, - identifiers[identifier].attestations[account].requested - ); - } - - function lookupAccountsForIdentifier(bytes32 identifier) - external - view - returns (address[] memory) - { - return identifiers[identifier].accounts; - } -} diff --git a/packages/protocol/contracts/identity/test/MockERC20Token.sol b/packages/protocol/contracts/identity/test/MockERC20Token.sol deleted file mode 100644 index eba32941a..000000000 --- a/packages/protocol/contracts/identity/test/MockERC20Token.sol +++ /dev/null @@ -1,28 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; - -contract MockERC20Token { - using SafeMath for uint256; - - mapping(address => uint256) private balances; - - function transfer(address to, uint256 value) external returns (bool) { - return transferFrom(msg.sender, to, value); - } - - function mint(address to, uint256 amount) external returns (bool) { - balances[to] = balances[to].add(amount); - return true; - } - - function balanceOf(address owner) external view returns (uint256) { - return balances[owner]; - } - - function transferFrom(address from, address to, uint256 value) public returns (bool) { - balances[from] = balances[from].sub(value); - balances[to] = balances[to].add(value); - return true; - } -} diff --git a/packages/protocol/contracts/identity/test/MockRandom.sol b/packages/protocol/contracts/identity/test/MockRandom.sol deleted file mode 100644 index bd0799964..000000000 --- a/packages/protocol/contracts/identity/test/MockRandom.sol +++ /dev/null @@ -1,15 +0,0 @@ -pragma solidity ^0.5.13; - -import "../Random.sol"; - -contract MockRandom is Random(true) { - mapping(uint256 => bytes32) private history; - - function addTestRandomness(uint256 blockNumber, bytes32 randomness) external { - history[blockNumber] = randomness; - } - function getBlockRandomness(uint256 blockNumber) external view returns (bytes32) { - require(history[blockNumber] != 0x0, "No randomness found"); - return history[blockNumber]; - } -} diff --git a/packages/protocol/contracts/identity/test/RandomTest.sol b/packages/protocol/contracts/identity/test/RandomTest.sol deleted file mode 100644 index b314589a0..000000000 --- a/packages/protocol/contracts/identity/test/RandomTest.sol +++ /dev/null @@ -1,17 +0,0 @@ -pragma solidity ^0.5.13; - -import "../Random.sol"; - -contract RandomTest is Random(true) { - function addTestRandomness(uint256 blockNumber, bytes32 randomness) external { - addRandomness(blockNumber, randomness); - } - function getTestRandomness(uint256 blockNumber, uint256 cur) external view returns (bytes32) { - return _getBlockRandomness(blockNumber, cur); - } - function testRevealAndCommit(bytes32 randomness, bytes32 newCommitment, address proposer) - external - { - _revealAndCommit(randomness, newCommitment, proposer); - } -} diff --git a/packages/protocol/contracts/package.json b/packages/protocol/contracts/package.json deleted file mode 100644 index f5e3d544e..000000000 --- a/packages/protocol/contracts/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "@celo/contracts", - "version": "0.0.0-template.version", - "author": "cLabs", - "license": "LGPL-3.0", - "repository": { - "type": "git", - "url": "https://github.com/celo-org/celo-monorepo.git", - "directory": "packages/protocol/contracts" - }, - "scripts": {}, - "dependencies": {} -} diff --git a/packages/protocol/contracts/stability/SortedOracles.sol b/packages/protocol/contracts/stability/SortedOracles.sol deleted file mode 100644 index 813d92312..000000000 --- a/packages/protocol/contracts/stability/SortedOracles.sol +++ /dev/null @@ -1,343 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./interfaces/ISortedOracles.sol"; -import "../common/interfaces/ICeloVersionedContract.sol"; - -import "../common/FixidityLib.sol"; -import "../common/Initializable.sol"; -import "../common/linkedlists/AddressSortedLinkedListWithMedian.sol"; -import "../common/linkedlists/SortedLinkedListWithMedian.sol"; - -/** - * @title Maintains a sorted list of oracle exchange rates between CELO and other currencies. - */ -contract SortedOracles is ISortedOracles, ICeloVersionedContract, Ownable, Initializable { - using SafeMath for uint256; - using AddressSortedLinkedListWithMedian for SortedLinkedListWithMedian.List; - using FixidityLib for FixidityLib.Fraction; - - uint256 private constant FIXED1_UINT = 1000000000000000000000000; - - // Maps a token address to a sorted list of report values. - mapping(address => SortedLinkedListWithMedian.List) private rates; - // Maps a token address to a sorted list of report timestamps. - mapping(address => SortedLinkedListWithMedian.List) private timestamps; - mapping(address => mapping(address => bool)) public isOracle; - mapping(address => address[]) public oracles; - - // `reportExpirySeconds` is the fallback value used to determine reporting - // frequency. Initially it was the _only_ value but we later introduced - // the per token mapping in `tokenReportExpirySeconds`. If a token - // doesn't have a value in the mapping (i.e. it's 0), the fallback is used. - // See: #getTokenReportExpirySeconds - uint256 public reportExpirySeconds; - mapping(address => uint256) public tokenReportExpirySeconds; - - event OracleAdded(address indexed token, address indexed oracleAddress); - event OracleRemoved(address indexed token, address indexed oracleAddress); - event OracleReported( - address indexed token, - address indexed oracle, - uint256 timestamp, - uint256 value - ); - event OracleReportRemoved(address indexed token, address indexed oracle); - event MedianUpdated(address indexed token, uint256 value); - event ReportExpirySet(uint256 reportExpiry); - event TokenReportExpirySet(address token, uint256 reportExpiry); - - modifier onlyOracle(address token) { - require(isOracle[token][msg.sender], "sender was not an oracle for token addr"); - _; - } - - /** - * @notice Returns the storage, major, minor, and patch version of the contract. - * @return Storage version of the contract. - * @return Major version of the contract. - * @return Minor version of the contract. - * @return Patch version of the contract. - */ - function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { - return (1, 1, 2, 3); - } - - /** - * @notice Sets initialized == true on implementation contracts - * @param test Set to true to skip implementation initialization - */ - constructor(bool test) public Initializable(test) {} - - /** - * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. - * @param _reportExpirySeconds The number of seconds before a report is considered expired. - */ - function initialize(uint256 _reportExpirySeconds) external initializer { - _transferOwnership(msg.sender); - setReportExpiry(_reportExpirySeconds); - } - - /** - * @notice Sets the report expiry parameter. - * @param _reportExpirySeconds The number of seconds before a report is considered expired. - */ - function setReportExpiry(uint256 _reportExpirySeconds) public onlyOwner { - require(_reportExpirySeconds > 0, "report expiry seconds must be > 0"); - require(_reportExpirySeconds != reportExpirySeconds, "reportExpirySeconds hasn't changed"); - reportExpirySeconds = _reportExpirySeconds; - emit ReportExpirySet(_reportExpirySeconds); - } - - /** - * @notice Sets the report expiry parameter for a token. - * @param _token The address of the token to set expiry for. - * @param _reportExpirySeconds The number of seconds before a report is considered expired. - */ - function setTokenReportExpiry(address _token, uint256 _reportExpirySeconds) external onlyOwner { - require(_reportExpirySeconds > 0, "report expiry seconds must be > 0"); - require( - _reportExpirySeconds != tokenReportExpirySeconds[_token], - "token reportExpirySeconds hasn't changed" - ); - tokenReportExpirySeconds[_token] = _reportExpirySeconds; - emit TokenReportExpirySet(_token, _reportExpirySeconds); - } - - /** - * @notice Adds a new Oracle. - * @param token The address of the token. - * @param oracleAddress The address of the oracle. - */ - function addOracle(address token, address oracleAddress) external onlyOwner { - require(token != address(0), "token addr was null"); - require(oracleAddress != address(0), "oracle addr was null"); - require(!isOracle[token][oracleAddress], "oracle addr is not an oracle for token addr"); - isOracle[token][oracleAddress] = true; - oracles[token].push(oracleAddress); - emit OracleAdded(token, oracleAddress); - } - - /** - * @notice Removes an Oracle. - * @param token The address of the token. - * @param oracleAddress The address of the oracle. - * @param index The index of `oracleAddress` in the list of oracles. - */ - function removeOracle(address token, address oracleAddress, uint256 index) external onlyOwner { - require( - token != address(0) && - oracleAddress != address(0) && - oracles[token].length > index && - oracles[token][index] == oracleAddress, - "token addr null or oracle addr null or index of token oracle not mapped to oracle addr" - ); - isOracle[token][oracleAddress] = false; - oracles[token][index] = oracles[token][oracles[token].length.sub(1)]; - oracles[token].length = oracles[token].length.sub(1); - if (reportExists(token, oracleAddress)) { - removeReport(token, oracleAddress); - } - emit OracleRemoved(token, oracleAddress); - } - - /** - * @notice Removes a report that is expired. - * @param token The address of the token for which the CELO exchange rate is being reported. - * @param n The number of expired reports to remove, at most (deterministic upper gas bound). - */ - function removeExpiredReports(address token, uint256 n) external { - require( - token != address(0) && n < timestamps[token].getNumElements(), - "token addr null or trying to remove too many reports" - ); - for (uint256 i = 0; i < n; i = i.add(1)) { - (bool isExpired, address oldestAddress) = isOldestReportExpired(token); - if (isExpired) { - removeReport(token, oldestAddress); - } else { - break; - } - } - } - - /** - * @notice Check if last report is expired. - * @param token The address of the token for which the CELO exchange rate is being reported. - * @return isExpired - * @return The address of the last report. - */ - function isOldestReportExpired(address token) public view returns (bool, address) { - require(token != address(0), "token address cannot be null"); - address oldest = timestamps[token].getTail(); - uint256 timestamp = timestamps[token].getValue(oldest); - // solhint-disable-next-line not-rely-on-time - if (now.sub(timestamp) >= getTokenReportExpirySeconds(token)) { - return (true, oldest); - } - return (false, oldest); - } - - /** - * @notice Updates an oracle value and the median. - * @param token The address of the token for which the CELO exchange rate is being reported. - * @param value The amount of `token` equal to one CELO, expressed as a fixidity value. - * @param lesserKey The element which should be just left of the new oracle value. - * @param greaterKey The element which should be just right of the new oracle value. - * @dev Note that only one of `lesserKey` or `greaterKey` needs to be correct to reduce friction. - */ - function report(address token, uint256 value, address lesserKey, address greaterKey) - external - onlyOracle(token) - { - uint256 originalMedian = rates[token].getMedianValue(); - if (rates[token].contains(msg.sender)) { - rates[token].update(msg.sender, value, lesserKey, greaterKey); - - // Rather than update the timestamp, we remove it and re-add it at the - // head of the list later. The reason for this is that we need to handle - // a few different cases: - // 1. This oracle is the only one to report so far. lesserKey = address(0) - // 2. Other oracles have reported since this one's last report. lesserKey = getHead() - // 3. Other oracles have reported, but the most recent is this one. - // lesserKey = key immediately after getHead() - // - // However, if we just remove this timestamp, timestamps[token].getHead() - // does the right thing in all cases. - timestamps[token].remove(msg.sender); - } else { - rates[token].insert(msg.sender, value, lesserKey, greaterKey); - } - timestamps[token].insert( - msg.sender, - // solhint-disable-next-line not-rely-on-time - now, - timestamps[token].getHead(), - address(0) - ); - emit OracleReported(token, msg.sender, now, value); - uint256 newMedian = rates[token].getMedianValue(); - if (newMedian != originalMedian) { - emit MedianUpdated(token, newMedian); - } - } - - /** - * @notice Returns the number of rates. - * @param token The address of the token for which the CELO exchange rate is being reported. - * @return The number of reported oracle rates for `token`. - */ - function numRates(address token) public view returns (uint256) { - return rates[token].getNumElements(); - } - - /** - * @notice Returns the median rate. - * @param token The address of the token for which the CELO exchange rate is being reported. - * @return The median exchange rate for `token`. - * @return fixidity - */ - function medianRate(address token) external view returns (uint256, uint256) { - return (rates[token].getMedianValue(), numRates(token) == 0 ? 0 : FIXED1_UINT); - } - - /** - * @notice Gets all elements from the doubly linked list. - * @param token The address of the token for which the CELO exchange rate is being reported. - * @return keys Keys of nn unpacked list of elements from largest to smallest. - * @return values Values of an unpacked list of elements from largest to smallest. - * @return relations Relations of an unpacked list of elements from largest to smallest. - */ - function getRates(address token) - external - view - returns (address[] memory, uint256[] memory, SortedLinkedListWithMedian.MedianRelation[] memory) - { - return rates[token].getElements(); - } - - /** - * @notice Returns the number of timestamps. - * @param token The address of the token for which the CELO exchange rate is being reported. - * @return The number of oracle report timestamps for `token`. - */ - function numTimestamps(address token) public view returns (uint256) { - return timestamps[token].getNumElements(); - } - - /** - * @notice Returns the median timestamp. - * @param token The address of the token for which the CELO exchange rate is being reported. - * @return The median report timestamp for `token`. - */ - function medianTimestamp(address token) external view returns (uint256) { - return timestamps[token].getMedianValue(); - } - - /** - * @notice Gets all elements from the doubly linked list. - * @param token The address of the token for which the CELO exchange rate is being reported. - * @return keys Keys of nn unpacked list of elements from largest to smallest. - * @return values Values of an unpacked list of elements from largest to smallest. - * @return relations Relations of an unpacked list of elements from largest to smallest. - */ - function getTimestamps(address token) - external - view - returns (address[] memory, uint256[] memory, SortedLinkedListWithMedian.MedianRelation[] memory) - { - return timestamps[token].getElements(); - } - - /** - * @notice Returns whether a report exists on token from oracle. - * @param token The address of the token for which the CELO exchange rate is being reported. - * @param oracle The oracle whose report should be checked. - */ - function reportExists(address token, address oracle) internal view returns (bool) { - return rates[token].contains(oracle) && timestamps[token].contains(oracle); - } - - /** - * @notice Returns the list of oracles for a particular token. - * @param token The address of the token whose oracles should be returned. - * @return The list of oracles for a particular token. - */ - function getOracles(address token) external view returns (address[] memory) { - return oracles[token]; - } - - /** - * @notice Returns the expiry for the token if exists, if not the default. - * @param token The address of the token. - * @return The report expiry in seconds. - */ - function getTokenReportExpirySeconds(address token) public view returns (uint256) { - if (tokenReportExpirySeconds[token] == 0) { - return reportExpirySeconds; - } - - return tokenReportExpirySeconds[token]; - } - - /** - * @notice Removes an oracle value and updates the median. - * @param token The address of the token for which the CELO exchange rate is being reported. - * @param oracle The oracle whose value should be removed. - * @dev This can be used to delete elements for oracles that have been removed. - * However, a > 1 elements reports list should always be maintained - */ - function removeReport(address token, address oracle) private { - if (numTimestamps(token) == 1 && reportExists(token, oracle)) return; - uint256 originalMedian = rates[token].getMedianValue(); - rates[token].remove(oracle); - timestamps[token].remove(oracle); - emit OracleReportRemoved(token, oracle); - uint256 newMedian = rates[token].getMedianValue(); - if (newMedian != originalMedian) { - emit MedianUpdated(token, newMedian); - } - } -} diff --git a/packages/protocol/contracts/stability/interfaces/ISortedOracles.sol b/packages/protocol/contracts/stability/interfaces/ISortedOracles.sol deleted file mode 100644 index bed0eca9e..000000000 --- a/packages/protocol/contracts/stability/interfaces/ISortedOracles.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.5.13 <0.9.0; - -interface ISortedOracles { - function addOracle(address, address) external; - function removeOracle(address, address, uint256) external; - function report(address, uint256, address, address) external; - function removeExpiredReports(address, uint256) external; - function isOldestReportExpired(address token) external view returns (bool, address); - function numRates(address) external view returns (uint256); - function medianRate(address) external view returns (uint256, uint256); - function numTimestamps(address) external view returns (uint256); - function medianTimestamp(address) external view returns (uint256); -} diff --git a/packages/protocol/contracts/stability/proxies/SortedOraclesProxy.sol b/packages/protocol/contracts/stability/proxies/SortedOraclesProxy.sol deleted file mode 100644 index 6098ab1e9..000000000 --- a/packages/protocol/contracts/stability/proxies/SortedOraclesProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "../../common/Proxy.sol"; - -/* solhint-disable-next-line no-empty-blocks */ -contract SortedOraclesProxy is Proxy {} diff --git a/packages/protocol/contracts/stability/test/MockReserve.sol b/packages/protocol/contracts/stability/test/MockReserve.sol deleted file mode 100644 index 4e28cdc49..000000000 --- a/packages/protocol/contracts/stability/test/MockReserve.sol +++ /dev/null @@ -1,43 +0,0 @@ -pragma solidity ^0.5.13; -// solhint-disable no-unused-vars - -import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; - -/** - * @title A mock Reserve for testing. - */ -contract MockReserve { - mapping(address => bool) public tokens; - - IERC20 public goldToken; - - // solhint-disable-next-line no-empty-blocks - function() external payable {} - - function setGoldToken(address goldTokenAddress) external { - goldToken = IERC20(goldTokenAddress); - } - - function transferGold(address to, uint256 value) external returns (bool) { - require(goldToken.transfer(to, value), "gold token transfer failed"); - return true; - } - - function transferExchangeGold(address to, uint256 value) external returns (bool) { - require(goldToken.transfer(to, value), "gold token transfer failed"); - return true; - } - - function addToken(address token) external returns (bool) { - tokens[token] = true; - return true; - } - - function burnToken(address) external pure returns (bool) { - return true; - } - - function getUnfrozenReserveGoldBalance() external view returns (uint256) { - return address(this).balance; - } -} diff --git a/packages/protocol/contracts/stability/test/MockSortedOracles.sol b/packages/protocol/contracts/stability/test/MockSortedOracles.sol deleted file mode 100644 index 6b35d2939..000000000 --- a/packages/protocol/contracts/stability/test/MockSortedOracles.sol +++ /dev/null @@ -1,49 +0,0 @@ -pragma solidity ^0.5.13; - -/** - * @title A mock SortedOracles for testing. - */ -contract MockSortedOracles { - uint256 public constant DENOMINATOR = 1000000000000000000000000; - mapping(address => uint256) public numerators; - mapping(address => uint256) public medianTimestamp; - mapping(address => uint256) public _numRates; - mapping(address => bool) public expired; - - function setMedianRate(address token, uint256 numerator) external returns (bool) { - numerators[token] = numerator; - return true; - } - - function setMedianTimestamp(address token, uint256 timestamp) external { - medianTimestamp[token] = timestamp; - } - - function setMedianTimestampToNow(address token) external { - // solhint-disable-next-line not-rely-on-time - medianTimestamp[token] = uint128(now); - } - - function setNumRates(address token, uint256 rate) external { - _numRates[token] = rate; // This change may breack something, TODO - } - - function numRates(address token) external view returns (uint256) { - return _numRates[token]; - } - - function medianRate(address token) external view returns (uint256, uint256) { - if (numerators[token] > 0) { - return (numerators[token], DENOMINATOR); - } - return (0, 0); - } - - function isOldestReportExpired(address token) public view returns (bool, address) { - return (expired[token], token); - } - - function setOldestReportExpired(address token) public { - expired[token] = true; - } -} diff --git a/packages/protocol/contracts/stability/test/MockStableToken.sol b/packages/protocol/contracts/stability/test/MockStableToken.sol deleted file mode 100644 index fe5e1244b..000000000 --- a/packages/protocol/contracts/stability/test/MockStableToken.sol +++ /dev/null @@ -1,81 +0,0 @@ -pragma solidity ^0.5.13; -// solhint-disable no-unused-vars - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; - -import "../../common/FixidityLib.sol"; - -/** - * @title A mock StableToken for testing. - */ -contract MockStableToken { - using FixidityLib for FixidityLib.Fraction; - using SafeMath for uint256; - - uint8 public constant decimals = 18; - uint256 public _totalSupply; - FixidityLib.Fraction public inflationFactor; - - // Stored as units. Value can be found using unitsToValue(). - mapping(address => uint256) public balances; - - constructor() public { - setInflationFactor(FixidityLib.fixed1().unwrap()); - } - - function setInflationFactor(uint256 newInflationFactor) public { - inflationFactor = FixidityLib.wrap(newInflationFactor); - } - - function setTotalSupply(uint256 value) external { - _totalSupply = value; - } - - function mint(address to, uint256 value) external returns (bool) { - require(to != address(0), "0 is a reserved address"); - balances[to] = balances[to].add(valueToUnits(value)); - _totalSupply = _totalSupply.add(value); - return true; - } - - function burn(uint256 value) external returns (bool) { - balances[msg.sender] = balances[msg.sender].sub(valueToUnits(value)); - _totalSupply = _totalSupply.sub(value); - return true; - } - - function totalSupply() external view returns (uint256) { - return _totalSupply; - } - - function transfer(address to, uint256 value) external returns (bool) { - return _transfer(msg.sender, to, value); - } - - function transferFrom(address from, address to, uint256 value) external returns (bool) { - return _transfer(from, to, value); - } - - function _transfer(address from, address to, uint256 value) internal returns (bool) { - uint256 balanceValue = balanceOf(from); - if (balanceValue < value) { - return false; - } - uint256 units = valueToUnits(value); - balances[from] = balances[from].sub(units); - balances[to] = balances[to].add(units); - return true; - } - - function balanceOf(address account) public view returns (uint256) { - return unitsToValue(balances[account]); - } - - function unitsToValue(uint256 units) public view returns (uint256) { - return FixidityLib.newFixed(units).divide(inflationFactor).fromFixed(); - } - - function valueToUnits(uint256 value) public view returns (uint256) { - return inflationFactor.multiply(FixidityLib.newFixed(value)).fromFixed(); - } -} diff --git a/packages/protocol/contracts/uniswap/interfaces/IUniswapV2Callee.sol b/packages/protocol/contracts/uniswap/interfaces/IUniswapV2Callee.sol deleted file mode 100644 index bc743252f..000000000 --- a/packages/protocol/contracts/uniswap/interfaces/IUniswapV2Callee.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity >=0.5.0; - -interface IUniswapV2Callee { - function uniswapV2Call(address sender, uint256 amount0, uint256 amount1, bytes calldata data) - external; -} diff --git a/packages/protocol/contracts/uniswap/interfaces/IUniswapV2ERC20.sol b/packages/protocol/contracts/uniswap/interfaces/IUniswapV2ERC20.sol deleted file mode 100644 index d7d78ca86..000000000 --- a/packages/protocol/contracts/uniswap/interfaces/IUniswapV2ERC20.sol +++ /dev/null @@ -1,31 +0,0 @@ -pragma solidity >=0.5.0; - -interface IUniswapV2ERC20 { - event Approval(address indexed owner, address indexed spender, uint256 value); - event Transfer(address indexed from, address indexed to, uint256 value); - - function name() external pure returns (string memory); - function symbol() external pure returns (string memory); - function decimals() external pure returns (uint8); - function totalSupply() external view returns (uint256); - function balanceOf(address owner) external view returns (uint256); - function allowance(address owner, address spender) external view returns (uint256); - - function approve(address spender, uint256 value) external returns (bool); - function transfer(address to, uint256 value) external returns (bool); - function transferFrom(address from, address to, uint256 value) external returns (bool); - - function DOMAIN_SEPARATOR() external view returns (bytes32); - function PERMIT_TYPEHASH() external pure returns (bytes32); - function nonces(address owner) external view returns (uint256); - - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; -} diff --git a/packages/protocol/contracts/uniswap/interfaces/IUniswapV2Factory.sol b/packages/protocol/contracts/uniswap/interfaces/IUniswapV2Factory.sol deleted file mode 100644 index f682c23a9..000000000 --- a/packages/protocol/contracts/uniswap/interfaces/IUniswapV2Factory.sol +++ /dev/null @@ -1,17 +0,0 @@ -pragma solidity >=0.5.0; - -interface IUniswapV2Factory { - event PairCreated(address indexed token0, address indexed token1, address pair, uint256); - - function feeTo() external view returns (address); - function feeToSetter() external view returns (address); - - function getPair(address tokenA, address tokenB) external view returns (address pair); - function allPairs(uint256) external view returns (address pair); - function allPairsLength() external view returns (uint256); - - function createPair(address tokenA, address tokenB) external returns (address pair); - - function setFeeTo(address) external; - function setFeeToSetter(address) external; -} diff --git a/packages/protocol/contracts/uniswap/interfaces/IUniswapV2FactoryMin.sol b/packages/protocol/contracts/uniswap/interfaces/IUniswapV2FactoryMin.sol deleted file mode 100644 index 81123b6fe..000000000 --- a/packages/protocol/contracts/uniswap/interfaces/IUniswapV2FactoryMin.sol +++ /dev/null @@ -1,5 +0,0 @@ -pragma solidity >=0.5.0; - -interface IUniswapV2FactoryMin { - function getPair(address tokenA, address tokenB) external view returns (address pair); -} diff --git a/packages/protocol/contracts/uniswap/interfaces/IUniswapV2Pair.sol b/packages/protocol/contracts/uniswap/interfaces/IUniswapV2Pair.sol deleted file mode 100644 index aee72cd73..000000000 --- a/packages/protocol/contracts/uniswap/interfaces/IUniswapV2Pair.sol +++ /dev/null @@ -1,63 +0,0 @@ -pragma solidity >=0.5.0; - -interface IUniswapV2Pair { - event Approval(address indexed owner, address indexed spender, uint256 value); - event Transfer(address indexed from, address indexed to, uint256 value); - - function name() external pure returns (string memory); - function symbol() external pure returns (string memory); - function decimals() external pure returns (uint8); - function totalSupply() external view returns (uint256); - function balanceOf(address owner) external view returns (uint256); - function allowance(address owner, address spender) external view returns (uint256); - - function approve(address spender, uint256 value) external returns (bool); - function transfer(address to, uint256 value) external returns (bool); - function transferFrom(address from, address to, uint256 value) external returns (bool); - - function DOMAIN_SEPARATOR() external view returns (bytes32); - function PERMIT_TYPEHASH() external pure returns (bytes32); - function nonces(address owner) external view returns (uint256); - - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - event Mint(address indexed sender, uint256 amount0, uint256 amount1); - event Burn(address indexed sender, uint256 amount0, uint256 amount1, address indexed to); - event Swap( - address indexed sender, - uint256 amount0In, - uint256 amount1In, - uint256 amount0Out, - uint256 amount1Out, - address indexed to - ); - event Sync(uint112 reserve0, uint112 reserve1); - - function MINIMUM_LIQUIDITY() external pure returns (uint256); - function factory() external view returns (address); - function token0() external view returns (address); - function token1() external view returns (address); - function getReserves() - external - view - returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); - function price0CumulativeLast() external view returns (uint256); - function price1CumulativeLast() external view returns (uint256); - function kLast() external view returns (uint256); - - function mint(address to) external returns (uint256 liquidity); - function burn(address to) external returns (uint256 amount0, uint256 amount1); - function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data) external; - function skim(address to) external; - function sync() external; - - function initialize(address, address) external; -} diff --git a/packages/protocol/contracts/uniswap/interfaces/IUniswapV2Router02.sol b/packages/protocol/contracts/uniswap/interfaces/IUniswapV2Router02.sol deleted file mode 100644 index f8b45b7fc..000000000 --- a/packages/protocol/contracts/uniswap/interfaces/IUniswapV2Router02.sol +++ /dev/null @@ -1,170 +0,0 @@ -pragma solidity ^0.5.13; - -interface IUniswapV2Router02 { - function removeLiquidityETHSupportingFeeOnTransferTokens( - address token, - uint256 liquidity, - uint256 amountTokenMin, - uint256 amountETHMin, - address to, - uint256 deadline - ) external returns (uint256 amountETH); - function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( - address token, - uint256 liquidity, - uint256 amountTokenMin, - uint256 amountETHMin, - address to, - uint256 deadline, - bool approveMax, - uint8 v, - bytes32 r, - bytes32 s - ) external returns (uint256 amountETH); - - function swapExactTokensForTokensSupportingFeeOnTransferTokens( - uint256 amountIn, - uint256 amountOutMin, - address[] calldata path, - address to, - uint256 deadline - ) external; - function swapExactETHForTokensSupportingFeeOnTransferTokens( - uint256 amountOutMin, - address[] calldata path, - address to, - uint256 deadline - ) external payable; - function swapExactTokensForETHSupportingFeeOnTransferTokens( - uint256 amountIn, - uint256 amountOutMin, - address[] calldata path, - address to, - uint256 deadline - ) external; - - function factory() external pure returns (address); - function WETH() external pure returns (address); - - function addLiquidity( - address tokenA, - address tokenB, - uint256 amountADesired, - uint256 amountBDesired, - uint256 amountAMin, - uint256 amountBMin, - address to, - uint256 deadline - ) external returns (uint256 amountA, uint256 amountB, uint256 liquidity); - function addLiquidityETH( - address token, - uint256 amountTokenDesired, - uint256 amountTokenMin, - uint256 amountETHMin, - address to, - uint256 deadline - ) external payable returns (uint256 amountToken, uint256 amountETH, uint256 liquidity); - function removeLiquidity( - address tokenA, - address tokenB, - uint256 liquidity, - uint256 amountAMin, - uint256 amountBMin, - address to, - uint256 deadline - ) external returns (uint256 amountA, uint256 amountB); - function removeLiquidityETH( - address token, - uint256 liquidity, - uint256 amountTokenMin, - uint256 amountETHMin, - address to, - uint256 deadline - ) external returns (uint256 amountToken, uint256 amountETH); - function removeLiquidityWithPermit( - address tokenA, - address tokenB, - uint256 liquidity, - uint256 amountAMin, - uint256 amountBMin, - address to, - uint256 deadline, - bool approveMax, - uint8 v, - bytes32 r, - bytes32 s - ) external returns (uint256 amountA, uint256 amountB); - function removeLiquidityETHWithPermit( - address token, - uint256 liquidity, - uint256 amountTokenMin, - uint256 amountETHMin, - address to, - uint256 deadline, - bool approveMax, - uint8 v, - bytes32 r, - bytes32 s - ) external returns (uint256 amountToken, uint256 amountETH); - function swapExactTokensForTokens( - uint256 amountIn, - uint256 amountOutMin, - address[] calldata path, - address to, - uint256 deadline - ) external returns (uint256[] memory amounts); - function swapTokensForExactTokens( - uint256 amountOut, - uint256 amountInMax, - address[] calldata path, - address to, - uint256 deadline - ) external returns (uint256[] memory amounts); - function swapExactETHForTokens( - uint256 amountOutMin, - address[] calldata path, - address to, - uint256 deadline - ) external payable returns (uint256[] memory amounts); - function swapTokensForExactETH( - uint256 amountOut, - uint256 amountInMax, - address[] calldata path, - address to, - uint256 deadline - ) external returns (uint256[] memory amounts); - function swapExactTokensForETH( - uint256 amountIn, - uint256 amountOutMin, - address[] calldata path, - address to, - uint256 deadline - ) external returns (uint256[] memory amounts); - function swapETHForExactTokens( - uint256 amountOut, - address[] calldata path, - address to, - uint256 deadline - ) external payable returns (uint256[] memory amounts); - - function quote(uint256 amountA, uint256 reserveA, uint256 reserveB) - external - pure - returns (uint256 amountB); - function getAmountOut(uint256 amountIn, uint256 reserveIn, uint256 reserveOut) - external - pure - returns (uint256 amountOut); - function getAmountIn(uint256 amountOut, uint256 reserveIn, uint256 reserveOut) - external - pure - returns (uint256 amountIn); - function getAmountsOut(uint256 amountIn, address[] calldata path) - external - view - returns (uint256[] memory amounts); - function getAmountsIn(uint256 amountOut, address[] calldata path) - external - view - returns (uint256[] memory amounts); -} diff --git a/packages/protocol/contracts/uniswap/interfaces/IUniswapV2RouterMin.sol b/packages/protocol/contracts/uniswap/interfaces/IUniswapV2RouterMin.sol deleted file mode 100644 index a8715cc3e..000000000 --- a/packages/protocol/contracts/uniswap/interfaces/IUniswapV2RouterMin.sol +++ /dev/null @@ -1,16 +0,0 @@ -pragma solidity ^0.5.13; - -interface IUniswapV2RouterMin { - function factory() external pure returns (address); - function swapExactTokensForTokens( - uint256 amountIn, - uint256 amountOutMin, - address[] calldata path, - address to, - uint256 deadline - ) external returns (uint256[] memory amounts); - function getAmountsOut(uint256 amountIn, address[] calldata path) - external - view - returns (uint256[] memory amounts); -} diff --git a/packages/protocol/contracts/uniswap/interfaces/IWETH.sol b/packages/protocol/contracts/uniswap/interfaces/IWETH.sol deleted file mode 100644 index bdc7443db..000000000 --- a/packages/protocol/contracts/uniswap/interfaces/IWETH.sol +++ /dev/null @@ -1,7 +0,0 @@ -pragma solidity >=0.5.0; - -interface IWETH { - function deposit() external payable; - function transfer(address to, uint256 value) external returns (bool); - function withdraw(uint256) external; -} diff --git a/packages/protocol/contracts/uniswap/test/MockERC20.sol b/packages/protocol/contracts/uniswap/test/MockERC20.sol deleted file mode 100644 index db2e0a6f0..000000000 --- a/packages/protocol/contracts/uniswap/test/MockERC20.sol +++ /dev/null @@ -1,10 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol"; - -contract MockERC20 is ERC20 { - function mint(address account, uint256 amount) external { - _mint(account, amount); - } - -} diff --git a/packages/protocol/contracts/uniswap/test/MockUniswapV2Factory.sol b/packages/protocol/contracts/uniswap/test/MockUniswapV2Factory.sol deleted file mode 100644 index eba03411e..000000000 --- a/packages/protocol/contracts/uniswap/test/MockUniswapV2Factory.sol +++ /dev/null @@ -1,53 +0,0 @@ -pragma solidity ^0.5.13; - -import "../interfaces/IUniswapV2Factory.sol"; -import "./MockUniswapV2Pair.sol"; - -contract MockUniswapV2Factory is IUniswapV2Factory { - address public feeTo; - address public feeToSetter; - - mapping(address => mapping(address => address)) public getPair; - address[] public allPairs; - - bytes32 public constant INIT_CODE_PAIR_HASH = keccak256( - abi.encodePacked(type(MockUniswapV2Pair).creationCode) - ); - - event PairCreated(address indexed token0, address indexed token1, address pair, uint256); - - constructor(address _feeToSetter) public { - feeToSetter = _feeToSetter; - } - - function allPairsLength() external view returns (uint256) { - return allPairs.length; - } - - function createPair(address tokenA, address tokenB) external returns (address pair) { - require(tokenA != tokenB, "UniswapV2: IDENTICAL_ADDRESSES"); - (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); - require(token0 != address(0), "UniswapV2: ZERO_ADDRESS"); - require(getPair[token0][token1] == address(0), "UniswapV2: PAIR_EXISTS"); // single check is sufficient - bytes memory bytecode = type(MockUniswapV2Pair).creationCode; - bytes32 salt = keccak256(abi.encodePacked(token0, token1)); - assembly { - pair := create2(0, add(bytecode, 32), mload(bytecode), salt) - } - IUniswapV2Pair(pair).initialize(token0, token1); - getPair[token0][token1] = pair; - getPair[token1][token0] = pair; // populate mapping in the reverse direction - allPairs.push(pair); - emit PairCreated(token0, token1, pair, allPairs.length); - } - - function setFeeTo(address _feeTo) external { - require(msg.sender == feeToSetter, "UniswapV2: FORBIDDEN"); - feeTo = _feeTo; - } - - function setFeeToSetter(address _feeToSetter) external { - require(msg.sender == feeToSetter, "UniswapV2: FORBIDDEN"); - feeToSetter = _feeToSetter; - } -} diff --git a/packages/protocol/contracts/uniswap/test/MockUniswapV2Pair.sol b/packages/protocol/contracts/uniswap/test/MockUniswapV2Pair.sol deleted file mode 100644 index 55a11d0f2..000000000 --- a/packages/protocol/contracts/uniswap/test/MockUniswapV2Pair.sol +++ /dev/null @@ -1,228 +0,0 @@ -pragma solidity ^0.5.13; - -import "../interfaces/IUniswapV2Pair.sol"; -import "./UniswapV2ERC20.sol"; -import "./libraries/MathUni.sol"; -import "./libraries/UQ112x112.sol"; -import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; - -import "../interfaces/IUniswapV2Factory.sol"; -import "../interfaces/IUniswapV2Callee.sol"; - -contract MockUniswapV2Pair is IUniswapV2Pair, UniswapV2ERC20 { - using SafeMath for uint256; - using UQ112x112 for uint224; - - uint256 public constant MINIMUM_LIQUIDITY = 10**3; - bytes4 private constant SELECTOR = bytes4(keccak256(bytes("transfer(address,uint256)"))); - - address public factory; - address public token0; - address public token1; - - uint112 private reserve0; // uses single storage slot, accessible via getReserves - uint112 private reserve1; // uses single storage slot, accessible via getReserves - uint32 private blockTimestampLast; // uses single storage slot, accessible via getReserves - - uint256 public price0CumulativeLast; - uint256 public price1CumulativeLast; - uint256 public kLast; // reserve0 * reserve1, as of immediately after the most recent liquidity event - - uint256 private unlocked = 1; - modifier lock() { - require(unlocked == 1, "UniswapV2: LOCKED"); - unlocked = 0; - _; - unlocked = 1; - } - - function getReserves() - public - view - returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) - { - _reserve0 = reserve0; - _reserve1 = reserve1; - _blockTimestampLast = blockTimestampLast; - } - - function _safeTransfer(address token, address to, uint256 value) private { - (bool success, bytes memory data) = token.call(abi.encodeWithSelector(SELECTOR, to, value)); - require( - success && (data.length == 0 || abi.decode(data, (bool))), - "UniswapV2: TRANSFER_FAILED" - ); - } - - event Mint(address indexed sender, uint256 amount0, uint256 amount1); - event Burn(address indexed sender, uint256 amount0, uint256 amount1, address indexed to); - event Swap( - address indexed sender, - uint256 amount0In, - uint256 amount1In, - uint256 amount0Out, - uint256 amount1Out, - address indexed to - ); - event Sync(uint112 reserve0, uint112 reserve1); - - constructor() public { - factory = msg.sender; - } - - // called once by the factory at time of deployment - function initialize(address _token0, address _token1) external { - require(msg.sender == factory, "UniswapV2: FORBIDDEN"); // sufficient check - token0 = _token0; - token1 = _token1; - } - - // update reserves and, on the first call per block, price accumulators - function _update(uint256 balance0, uint256 balance1, uint112 _reserve0, uint112 _reserve1) - private - { - require(balance0 <= uint112(-1) && balance1 <= uint112(-1), "UniswapV2: OVERFLOW"); - uint32 blockTimestamp = uint32(block.timestamp % 2**32); - uint32 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired - if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) { - // * never overflows, and + overflow is desired - price0CumulativeLast += uint256(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * timeElapsed; - price1CumulativeLast += uint256(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * timeElapsed; - } - reserve0 = uint112(balance0); - reserve1 = uint112(balance1); - blockTimestampLast = blockTimestamp; - emit Sync(reserve0, reserve1); - } - - // if fee is on, mint liquidity equivalent to 1/6th of the growth in sqrt(k) - function _mintFee(uint112 _reserve0, uint112 _reserve1) private returns (bool feeOn) { - address feeTo = IUniswapV2Factory(factory).feeTo(); - feeOn = feeTo != address(0); - uint256 _kLast = kLast; // gas savings - if (feeOn) { - if (_kLast != 0) { - uint256 rootK = MathUni.sqrt(uint256(_reserve0).mul(_reserve1)); - uint256 rootKLast = MathUni.sqrt(_kLast); - if (rootK > rootKLast) { - uint256 numerator = totalSupply.mul(rootK.sub(rootKLast)); - uint256 denominator = rootK.mul(5).add(rootKLast); - uint256 liquidity = numerator / denominator; - if (liquidity > 0) _mint(feeTo, liquidity); - } - } - } else if (_kLast != 0) { - kLast = 0; - } - } - - // this low-level function should be called from a contract which performs important safety checks - function mint(address to) external lock returns (uint256 liquidity) { - (uint112 _reserve0, uint112 _reserve1, ) = getReserves(); // gas savings - uint256 balance0 = IERC20(token0).balanceOf(address(this)); - uint256 balance1 = IERC20(token1).balanceOf(address(this)); - uint256 amount0 = balance0.sub(_reserve0); - uint256 amount1 = balance1.sub(_reserve1); - - bool feeOn = _mintFee(_reserve0, _reserve1); - uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee - if (_totalSupply == 0) { - liquidity = MathUni.sqrt(amount0.mul(amount1)).sub(MINIMUM_LIQUIDITY); - _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens - } else { - liquidity = MathUni.min( - amount0.mul(_totalSupply) / _reserve0, - amount1.mul(_totalSupply) / _reserve1 - ); - } - require(liquidity > 0, "UniswapV2: INSUFFICIENT_LIQUIDITY_MINTED"); - _mint(to, liquidity); - - _update(balance0, balance1, _reserve0, _reserve1); - if (feeOn) kLast = uint256(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date - emit Mint(msg.sender, amount0, amount1); - } - - // this low-level function should be called from a contract which performs important safety checks - function burn(address to) external lock returns (uint256 amount0, uint256 amount1) { - (uint112 _reserve0, uint112 _reserve1, ) = getReserves(); // gas savings - address _token0 = token0; // gas savings - address _token1 = token1; // gas savings - uint256 balance0 = IERC20(_token0).balanceOf(address(this)); - uint256 balance1 = IERC20(_token1).balanceOf(address(this)); - uint256 liquidity = balanceOf[address(this)]; - - bool feeOn = _mintFee(_reserve0, _reserve1); - uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee - amount0 = liquidity.mul(balance0) / _totalSupply; // using balances ensures pro-rata distribution - amount1 = liquidity.mul(balance1) / _totalSupply; // using balances ensures pro-rata distribution - require(amount0 > 0 && amount1 > 0, "UniswapV2: INSUFFICIENT_LIQUIDITY_BURNED"); - _burn(address(this), liquidity); - _safeTransfer(_token0, to, amount0); - _safeTransfer(_token1, to, amount1); - balance0 = IERC20(_token0).balanceOf(address(this)); - balance1 = IERC20(_token1).balanceOf(address(this)); - - _update(balance0, balance1, _reserve0, _reserve1); - if (feeOn) kLast = uint256(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date - emit Burn(msg.sender, amount0, amount1, to); - } - - // this low-level function should be called from a contract which performs important safety checks - function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data) - external - lock - { - require(amount0Out > 0 || amount1Out > 0, "UniswapV2: INSUFFICIENT_OUTPUT_AMOUNT"); - (uint112 _reserve0, uint112 _reserve1, ) = getReserves(); // gas savings - require(amount0Out < _reserve0 && amount1Out < _reserve1, "UniswapV2: INSUFFICIENT_LIQUIDITY"); - - uint256 balance0; - uint256 balance1; - { - // scope for _token{0,1}, avoids stack too deep errors - address _token0 = token0; - address _token1 = token1; - require(to != _token0 && to != _token1, "UniswapV2: INVALID_TO"); - if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens - if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens - if (data.length > 0) - IUniswapV2Callee(to).uniswapV2Call(msg.sender, amount0Out, amount1Out, data); - balance0 = IERC20(_token0).balanceOf(address(this)); - balance1 = IERC20(_token1).balanceOf(address(this)); - } - uint256 amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0; - uint256 amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0; - require(amount0In > 0 || amount1In > 0, "UniswapV2: INSUFFICIENT_INPUT_AMOUNT"); - { - // scope for reserve{0,1}Adjusted, avoids stack too deep errors - uint256 balance0Adjusted = balance0.mul(1000).sub(amount0In.mul(3)); - uint256 balance1Adjusted = balance1.mul(1000).sub(amount1In.mul(3)); - require( - balance0Adjusted.mul(balance1Adjusted) >= uint256(_reserve0).mul(_reserve1).mul(1000**2), - "UniswapV2: K" - ); - } - - _update(balance0, balance1, _reserve0, _reserve1); - emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to); - } - - // force balances to match reserves - function skim(address to) external lock { - address _token0 = token0; // gas savings - address _token1 = token1; // gas savings - _safeTransfer(_token0, to, IERC20(_token0).balanceOf(address(this)).sub(reserve0)); - _safeTransfer(_token1, to, IERC20(_token1).balanceOf(address(this)).sub(reserve1)); - } - - // force reserves to match balances - function sync() external lock { - _update( - IERC20(token0).balanceOf(address(this)), - IERC20(token1).balanceOf(address(this)), - reserve0, - reserve1 - ); - } -} diff --git a/packages/protocol/contracts/uniswap/test/MockUniswapV2Router02.sol b/packages/protocol/contracts/uniswap/test/MockUniswapV2Router02.sol deleted file mode 100644 index b44d36810..000000000 --- a/packages/protocol/contracts/uniswap/test/MockUniswapV2Router02.sol +++ /dev/null @@ -1,543 +0,0 @@ -pragma solidity ^0.5.13; - -// Lines with line with a comment `CHANGED` was changed from original -// implementation to make it compatible with Solidity 0.5. -// As this is a mock, security is not a concern. - -import "../interfaces/IUniswapV2Factory.sol"; -import ".//libraries/TransferHelper.sol"; - -import "../interfaces/IUniswapV2Router02.sol"; -import "./libraries/UniswapV2Library.sol"; -import "./libraries/SafeMathUni.sol"; -import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; -import "../interfaces/IWETH.sol"; - -contract MockUniswapV2Router02 is IUniswapV2Router02 { - using SafeMathUni for uint256; - - address public factory; // CHANGED - address public WETH; // CHANGED - - bytes32 public INIT_CODE_PAIR_HASH; - - event Pair(address pair); - modifier ensure(uint256 deadline) { - require(deadline >= block.timestamp, "UniswapV2Router: EXPIRED"); - _; - } - - constructor(address _factory, address _WETH, bytes32 initCodePairHash) public { - factory = _factory; - WETH = _WETH; - INIT_CODE_PAIR_HASH = initCodePairHash; - } - - // receive() external payable { - // assert(msg.sender == WETH); // only accept ETH via fallback from the WETH contract - // } - - // **** ADD LIQUIDITY **** - function _addLiquidity( - address tokenA, - address tokenB, - uint256 amountADesired, - uint256 amountBDesired, - uint256 amountAMin, - uint256 amountBMin - ) internal returns (uint256 amountA, uint256 amountB) { - // create the pair if it doesn't exist yet - if (IUniswapV2Factory(factory).getPair(tokenA, tokenB) == address(0)) { - IUniswapV2Factory(factory).createPair(tokenA, tokenB); - } - // emit Pair(UniswapV2Library.pairFor(factory, tokenA, tokenB)), INIT_CODE_PAIR_HASH; - // require(false, "revert here"); - (amountA, amountA); - (uint256 reserveA, uint256 reserveB) = UniswapV2Library.getReserves( - factory, - tokenA, - tokenB, - INIT_CODE_PAIR_HASH - ); - if (reserveA == 0 && reserveB == 0) { - (amountA, amountB) = (amountADesired, amountBDesired); - } else { - uint256 amountBOptimal = UniswapV2Library.quote(amountADesired, reserveA, reserveB); - if (amountBOptimal <= amountBDesired) { - require(amountBOptimal >= amountBMin, "UniswapV2Router: INSUFFICIENT_B_AMOUNT"); - (amountA, amountB) = (amountADesired, amountBOptimal); - } else { - uint256 amountAOptimal = UniswapV2Library.quote(amountBDesired, reserveB, reserveA); - assert(amountAOptimal <= amountADesired); - require(amountAOptimal >= amountAMin, "UniswapV2Router: INSUFFICIENT_A_AMOUNT"); - (amountA, amountB) = (amountAOptimal, amountBDesired); - } - } - } - function addLiquidity( - address tokenA, - address tokenB, - uint256 amountADesired, - uint256 amountBDesired, - uint256 amountAMin, - uint256 amountBMin, - address to, - uint256 deadline - ) external ensure(deadline) returns (uint256 amountA, uint256 amountB, uint256 liquidity) { - (amountA, amountB) = _addLiquidity( - tokenA, - tokenB, - amountADesired, - amountBDesired, - amountAMin, - amountBMin - ); - // require(false, "revert here"); - address pair = UniswapV2Library.pairFor(factory, tokenA, tokenB, INIT_CODE_PAIR_HASH); - TransferHelper.safeTransferFrom(tokenA, msg.sender, pair, amountA); - TransferHelper.safeTransferFrom(tokenB, msg.sender, pair, amountB); - liquidity = IUniswapV2Pair(pair).mint(to); - } - function addLiquidityETH( - address token, - uint256 amountTokenDesired, - uint256 amountTokenMin, - uint256 amountETHMin, - address to, - uint256 deadline - ) - external - payable - ensure(deadline) - returns (uint256 amountToken, uint256 amountETH, uint256 liquidity) - { - (amountToken, amountETH) = _addLiquidity( - token, - WETH, - amountTokenDesired, - msg.value, - amountTokenMin, - amountETHMin - ); - address pair = UniswapV2Library.pairFor(factory, token, WETH, INIT_CODE_PAIR_HASH); - TransferHelper.safeTransferFrom(token, msg.sender, pair, amountToken); - // IWETH(WETH).deposit{value: amountETH}(); // CHANGED - assert(IWETH(WETH).transfer(pair, amountETH)); - liquidity = IUniswapV2Pair(pair).mint(to); - // refund dust eth, if any - if (msg.value > amountETH) TransferHelper.safeTransferETH(msg.sender, msg.value - amountETH); - } - - // **** REMOVE LIQUIDITY **** - function removeLiquidity( - address tokenA, - address tokenB, - uint256 liquidity, - uint256 amountAMin, - uint256 amountBMin, - address to, - uint256 deadline - ) public ensure(deadline) returns (uint256 amountA, uint256 amountB) { - address pair = UniswapV2Library.pairFor(factory, tokenA, tokenB, INIT_CODE_PAIR_HASH); - IUniswapV2Pair(pair).transferFrom(msg.sender, pair, liquidity); // send liquidity to pair - (uint256 amount0, uint256 amount1) = IUniswapV2Pair(pair).burn(to); - (address token0, ) = UniswapV2Library.sortTokens(tokenA, tokenB); - (amountA, amountB) = tokenA == token0 ? (amount0, amount1) : (amount1, amount0); - require(amountA >= amountAMin, "UniswapV2Router: INSUFFICIENT_A_AMOUNT"); - require(amountB >= amountBMin, "UniswapV2Router: INSUFFICIENT_B_AMOUNT"); - } - function removeLiquidityETH( - address token, - uint256 liquidity, - uint256 amountTokenMin, - uint256 amountETHMin, - address to, - uint256 deadline - ) public ensure(deadline) returns (uint256 amountToken, uint256 amountETH) { - (amountToken, amountETH) = removeLiquidity( - token, - WETH, - liquidity, - amountTokenMin, - amountETHMin, - address(this), - deadline - ); - TransferHelper.safeTransfer(token, to, amountToken); - IWETH(WETH).withdraw(amountETH); - TransferHelper.safeTransferETH(to, amountETH); - } - function removeLiquidityWithPermit( - address tokenA, - address tokenB, - uint256 liquidity, - uint256 amountAMin, - uint256 amountBMin, - address to, - uint256 deadline, - bool approveMax, - uint8 v, - bytes32 r, - bytes32 s - ) external returns (uint256 amountA, uint256 amountB) { - address pair = UniswapV2Library.pairFor(factory, tokenA, tokenB, INIT_CODE_PAIR_HASH); - uint256 value = approveMax ? uint256(-1) : liquidity; - IUniswapV2Pair(pair).permit(msg.sender, address(this), value, deadline, v, r, s); - (amountA, amountB) = removeLiquidity( - tokenA, - tokenB, - liquidity, - amountAMin, - amountBMin, - to, - deadline - ); - } - function removeLiquidityETHWithPermit( - address token, - uint256 liquidity, - uint256 amountTokenMin, - uint256 amountETHMin, - address to, - uint256 deadline, - bool approveMax, - uint8 v, - bytes32 r, - bytes32 s - ) external returns (uint256 amountToken, uint256 amountETH) { - address pair = UniswapV2Library.pairFor(factory, token, WETH, INIT_CODE_PAIR_HASH); - uint256 value = approveMax ? uint256(-1) : liquidity; - IUniswapV2Pair(pair).permit(msg.sender, address(this), value, deadline, v, r, s); - (amountToken, amountETH) = removeLiquidityETH( - token, - liquidity, - amountTokenMin, - amountETHMin, - to, - deadline - ); - } - - // **** REMOVE LIQUIDITY (supporting fee-on-transfer tokens) **** - function removeLiquidityETHSupportingFeeOnTransferTokens( - address token, - uint256 liquidity, - uint256 amountTokenMin, - uint256 amountETHMin, - address to, - uint256 deadline - ) public ensure(deadline) returns (uint256 amountETH) { - (, amountETH) = removeLiquidity( - token, - WETH, - liquidity, - amountTokenMin, - amountETHMin, - address(this), - deadline - ); - TransferHelper.safeTransfer(token, to, IERC20(token).balanceOf(address(this))); - IWETH(WETH).withdraw(amountETH); - TransferHelper.safeTransferETH(to, amountETH); - } - function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( - address token, - uint256 liquidity, - uint256 amountTokenMin, - uint256 amountETHMin, - address to, - uint256 deadline, - bool approveMax, - uint8 v, - bytes32 r, - bytes32 s - ) external returns (uint256 amountETH) { - address pair = UniswapV2Library.pairFor(factory, token, WETH, INIT_CODE_PAIR_HASH); - uint256 value = approveMax ? uint256(-1) : liquidity; - IUniswapV2Pair(pair).permit(msg.sender, address(this), value, deadline, v, r, s); - amountETH = removeLiquidityETHSupportingFeeOnTransferTokens( - token, - liquidity, - amountTokenMin, - amountETHMin, - to, - deadline - ); - } - - // **** SWAP **** - // requires the initial amount to have already been sent to the first pair - function _swap(uint256[] memory amounts, address[] memory path, address _to) internal { - for (uint256 i; i < path.length - 1; i++) { - (address input, address output) = (path[i], path[i + 1]); - (address token0, ) = UniswapV2Library.sortTokens(input, output); - uint256 amountOut = amounts[i + 1]; - (uint256 amount0Out, uint256 amount1Out) = input == token0 - ? (uint256(0), amountOut) - : (amountOut, uint256(0)); - address to = i < path.length - 2 - ? UniswapV2Library.pairFor(factory, output, path[i + 2], INIT_CODE_PAIR_HASH) - : _to; - IUniswapV2Pair(UniswapV2Library.pairFor(factory, input, output, INIT_CODE_PAIR_HASH)).swap( - amount0Out, - amount1Out, - to, - new bytes(0) - ); - } - } - function swapExactTokensForTokens( - uint256 amountIn, - uint256 amountOutMin, - address[] calldata path, - address to, - uint256 deadline - ) external ensure(deadline) returns (uint256[] memory amounts) { - amounts = UniswapV2Library.getAmountsOut(factory, amountIn, path, INIT_CODE_PAIR_HASH); - require( - amounts[amounts.length - 1] >= amountOutMin, - "UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT" - ); - TransferHelper.safeTransferFrom( - path[0], - msg.sender, - UniswapV2Library.pairFor(factory, path[0], path[1], INIT_CODE_PAIR_HASH), - amounts[0] - ); - _swap(amounts, path, to); - } - function swapTokensForExactTokens( - uint256 amountOut, - uint256 amountInMax, - address[] calldata path, - address to, - uint256 deadline - ) external ensure(deadline) returns (uint256[] memory amounts) { - amounts = UniswapV2Library.getAmountsIn(factory, amountOut, path, INIT_CODE_PAIR_HASH); - require(amounts[0] <= amountInMax, "UniswapV2Router: EXCESSIVE_INPUT_AMOUNT"); - TransferHelper.safeTransferFrom( - path[0], - msg.sender, - UniswapV2Library.pairFor(factory, path[0], path[1], INIT_CODE_PAIR_HASH), - amounts[0] - ); - _swap(amounts, path, to); - } - function swapExactETHForTokens( - uint256 amountOutMin, - address[] calldata path, - address to, - uint256 deadline - ) external payable ensure(deadline) returns (uint256[] memory amounts) { - require(path[0] == WETH, "UniswapV2Router: INVALID_PATH"); - amounts = UniswapV2Library.getAmountsOut(factory, msg.value, path, INIT_CODE_PAIR_HASH); - require( - amounts[amounts.length - 1] >= amountOutMin, - "UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT" - ); - // IWETH(WETH).deposit{value: amounts[0]}(); // CHANGED - assert( - IWETH(WETH).transfer( - UniswapV2Library.pairFor(factory, path[0], path[1], INIT_CODE_PAIR_HASH), - amounts[0] - ) - ); - _swap(amounts, path, to); - } - function swapTokensForExactETH( - uint256 amountOut, - uint256 amountInMax, - address[] calldata path, - address to, - uint256 deadline - ) external ensure(deadline) returns (uint256[] memory amounts) { - require(path[path.length - 1] == WETH, "UniswapV2Router: INVALID_PATH"); - amounts = UniswapV2Library.getAmountsIn(factory, amountOut, path, INIT_CODE_PAIR_HASH); - require(amounts[0] <= amountInMax, "UniswapV2Router: EXCESSIVE_INPUT_AMOUNT"); - TransferHelper.safeTransferFrom( - path[0], - msg.sender, - UniswapV2Library.pairFor(factory, path[0], path[1], INIT_CODE_PAIR_HASH), - amounts[0] - ); - _swap(amounts, path, address(this)); - IWETH(WETH).withdraw(amounts[amounts.length - 1]); - TransferHelper.safeTransferETH(to, amounts[amounts.length - 1]); - } - function swapExactTokensForETH( - uint256 amountIn, - uint256 amountOutMin, - address[] calldata path, - address to, - uint256 deadline - ) external ensure(deadline) returns (uint256[] memory amounts) { - require(path[path.length - 1] == WETH, "UniswapV2Router: INVALID_PATH"); - amounts = UniswapV2Library.getAmountsOut(factory, amountIn, path, INIT_CODE_PAIR_HASH); - require( - amounts[amounts.length - 1] >= amountOutMin, - "UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT" - ); - TransferHelper.safeTransferFrom( - path[0], - msg.sender, - UniswapV2Library.pairFor(factory, path[0], path[1], INIT_CODE_PAIR_HASH), - amounts[0] - ); - _swap(amounts, path, address(this)); - IWETH(WETH).withdraw(amounts[amounts.length - 1]); - TransferHelper.safeTransferETH(to, amounts[amounts.length - 1]); - } - function swapETHForExactTokens( - uint256 amountOut, - address[] calldata path, - address to, - uint256 deadline - ) external payable ensure(deadline) returns (uint256[] memory amounts) { - require(path[0] == WETH, "UniswapV2Router: INVALID_PATH"); - amounts = UniswapV2Library.getAmountsIn(factory, amountOut, path, INIT_CODE_PAIR_HASH); - require(amounts[0] <= msg.value, "UniswapV2Router: EXCESSIVE_INPUT_AMOUNT"); - // IWETH(WETH).deposit{value: amounts[0]}(); // CHANGED - assert( - IWETH(WETH).transfer( - UniswapV2Library.pairFor(factory, path[0], path[1], INIT_CODE_PAIR_HASH), - amounts[0] - ) - ); - _swap(amounts, path, to); - // refund dust eth, if any - if (msg.value > amounts[0]) TransferHelper.safeTransferETH(msg.sender, msg.value - amounts[0]); - } - - // **** SWAP (supporting fee-on-transfer tokens) **** - // requires the initial amount to have already been sent to the first pair - function _swapSupportingFeeOnTransferTokens(address[] memory path, address _to) internal { - for (uint256 i; i < path.length - 1; i++) { - (address input, address output) = (path[i], path[i + 1]); - (address token0, ) = UniswapV2Library.sortTokens(input, output); - IUniswapV2Pair pair = IUniswapV2Pair( - UniswapV2Library.pairFor(factory, input, output, INIT_CODE_PAIR_HASH) - ); - uint256 amountInput; - uint256 amountOutput; - { - // scope to avoid stack too deep errors - (uint256 reserve0, uint256 reserve1, ) = pair.getReserves(); - (uint256 reserveInput, uint256 reserveOutput) = input == token0 - ? (reserve0, reserve1) - : (reserve1, reserve0); - amountInput = IERC20(input).balanceOf(address(pair)).sub(reserveInput); - amountOutput = UniswapV2Library.getAmountOut(amountInput, reserveInput, reserveOutput); - } - (uint256 amount0Out, uint256 amount1Out) = input == token0 - ? (uint256(0), amountOutput) - : (amountOutput, uint256(0)); - address to = i < path.length - 2 - ? UniswapV2Library.pairFor(factory, output, path[i + 2], INIT_CODE_PAIR_HASH) - : _to; - pair.swap(amount0Out, amount1Out, to, new bytes(0)); - } - } - function swapExactTokensForTokensSupportingFeeOnTransferTokens( - uint256 amountIn, - uint256 amountOutMin, - address[] calldata path, - address to, - uint256 deadline - ) external ensure(deadline) { - TransferHelper.safeTransferFrom( - path[0], - msg.sender, - UniswapV2Library.pairFor(factory, path[0], path[1], INIT_CODE_PAIR_HASH), - amountIn - ); - uint256 balanceBefore = IERC20(path[path.length - 1]).balanceOf(to); - _swapSupportingFeeOnTransferTokens(path, to); - require( - IERC20(path[path.length - 1]).balanceOf(to).sub(balanceBefore) >= amountOutMin, - "UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT" - ); - } - function swapExactETHForTokensSupportingFeeOnTransferTokens( - uint256 amountOutMin, - address[] calldata path, - address to, - uint256 deadline - ) external payable ensure(deadline) { - require(path[0] == WETH, "UniswapV2Router: INVALID_PATH"); - uint256 amountIn = msg.value; - // IWETH(WETH).deposit{value: amountIn}(); // CHANGED - assert( - IWETH(WETH).transfer( - UniswapV2Library.pairFor(factory, path[0], path[1], INIT_CODE_PAIR_HASH), - amountIn - ) - ); - uint256 balanceBefore = IERC20(path[path.length - 1]).balanceOf(to); - _swapSupportingFeeOnTransferTokens(path, to); - require( - IERC20(path[path.length - 1]).balanceOf(to).sub(balanceBefore) >= amountOutMin, - "UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT" - ); - } - function swapExactTokensForETHSupportingFeeOnTransferTokens( - uint256 amountIn, - uint256 amountOutMin, - address[] calldata path, - address to, - uint256 deadline - ) external ensure(deadline) { - require(path[path.length - 1] == WETH, "UniswapV2Router: INVALID_PATH"); - TransferHelper.safeTransferFrom( - path[0], - msg.sender, - UniswapV2Library.pairFor(factory, path[0], path[1], INIT_CODE_PAIR_HASH), - amountIn - ); - _swapSupportingFeeOnTransferTokens(path, address(this)); - uint256 amountOut = IERC20(WETH).balanceOf(address(this)); - require(amountOut >= amountOutMin, "UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT"); - IWETH(WETH).withdraw(amountOut); - TransferHelper.safeTransferETH(to, amountOut); - } - - // **** LIBRARY FUNCTIONS **** - function quote(uint256 amountA, uint256 reserveA, uint256 reserveB) - public - pure - returns (uint256 amountB) - { - return UniswapV2Library.quote(amountA, reserveA, reserveB); - } - - function getAmountOut(uint256 amountIn, uint256 reserveIn, uint256 reserveOut) - public - pure - returns (uint256 amountOut) - { - return UniswapV2Library.getAmountOut(amountIn, reserveIn, reserveOut); - } - - function getAmountIn(uint256 amountOut, uint256 reserveIn, uint256 reserveOut) - public - pure - returns (uint256 amountIn) - { - return UniswapV2Library.getAmountIn(amountOut, reserveIn, reserveOut); - } - - function getAmountsOut(uint256 amountIn, address[] memory path) - public - view - returns (uint256[] memory amounts) - { - return UniswapV2Library.getAmountsOut(factory, amountIn, path, INIT_CODE_PAIR_HASH); - } - - function getAmountsIn(uint256 amountOut, address[] memory path) - public - view - returns (uint256[] memory amounts) - { - return UniswapV2Library.getAmountsIn(factory, amountOut, path, INIT_CODE_PAIR_HASH); - } -} diff --git a/packages/protocol/contracts/uniswap/test/UniswapV2ERC20.sol b/packages/protocol/contracts/uniswap/test/UniswapV2ERC20.sol deleted file mode 100644 index f96445acd..000000000 --- a/packages/protocol/contracts/uniswap/test/UniswapV2ERC20.sol +++ /dev/null @@ -1,107 +0,0 @@ -pragma solidity ^0.5.13; - -import "../interfaces/IUniswapV2ERC20.sol"; -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; - -contract UniswapV2ERC20 is IUniswapV2ERC20 { - using SafeMath for uint256; - - string public constant name = "Uniswap V2"; - string public constant symbol = "UNI-V2"; - uint8 public constant decimals = 18; - uint256 public totalSupply; - mapping(address => uint256) public balanceOf; - mapping(address => mapping(address => uint256)) public allowance; - - bytes32 public DOMAIN_SEPARATOR; - // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); - bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; - mapping(address => uint256) public nonces; - - event Approval(address indexed owner, address indexed spender, uint256 value); - event Transfer(address indexed from, address indexed to, uint256 value); - - constructor() public { - uint256 chainId; - assembly { - chainId := chainid - } - DOMAIN_SEPARATOR = keccak256( - abi.encode( - keccak256( - "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" - ), - keccak256(bytes(name)), - keccak256(bytes("1")), - chainId, - address(this) - ) - ); - } - - function _mint(address to, uint256 value) internal { - totalSupply = totalSupply.add(value); - balanceOf[to] = balanceOf[to].add(value); - emit Transfer(address(0), to, value); - } - - function _burn(address from, uint256 value) internal { - balanceOf[from] = balanceOf[from].sub(value); - totalSupply = totalSupply.sub(value); - emit Transfer(from, address(0), value); - } - - function _approve(address owner, address spender, uint256 value) private { - allowance[owner][spender] = value; - emit Approval(owner, spender, value); - } - - function _transfer(address from, address to, uint256 value) private { - balanceOf[from] = balanceOf[from].sub(value); - balanceOf[to] = balanceOf[to].add(value); - emit Transfer(from, to, value); - } - - function approve(address spender, uint256 value) external returns (bool) { - _approve(msg.sender, spender, value); - return true; - } - - function transfer(address to, uint256 value) external returns (bool) { - _transfer(msg.sender, to, value); - return true; - } - - function transferFrom(address from, address to, uint256 value) external returns (bool) { - if (allowance[from][msg.sender] != uint256(-1)) { - allowance[from][msg.sender] = allowance[from][msg.sender].sub(value); - } - _transfer(from, to, value); - return true; - } - - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external { - require(deadline >= block.timestamp, "UniswapV2: EXPIRED"); - bytes32 digest = keccak256( - abi.encodePacked( - "\x19\x01", - DOMAIN_SEPARATOR, - keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline)) - ) - ); - address recoveredAddress = ecrecover(digest, v, r, s); - require( - recoveredAddress != address(0) && recoveredAddress == owner, - "UniswapV2: INVALID_SIGNATURE" - ); - _approve(owner, spender, value); - } -} diff --git a/packages/protocol/contracts/uniswap/test/libraries/MathUni.sol b/packages/protocol/contracts/uniswap/test/libraries/MathUni.sol deleted file mode 100644 index 63f7722bb..000000000 --- a/packages/protocol/contracts/uniswap/test/libraries/MathUni.sol +++ /dev/null @@ -1,23 +0,0 @@ -pragma solidity ^0.5.13; - -// a library for performing various math operations - -library MathUni { - function min(uint256 x, uint256 y) internal pure returns (uint256 z) { - z = x < y ? x : y; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrt(uint256 y) internal pure returns (uint256 z) { - if (y > 3) { - z = y; - uint256 x = y / 2 + 1; - while (x < z) { - z = x; - x = (y / x + x) / 2; - } - } else if (y != 0) { - z = 1; - } - } -} diff --git a/packages/protocol/contracts/uniswap/test/libraries/SafeMathUni.sol b/packages/protocol/contracts/uniswap/test/libraries/SafeMathUni.sol deleted file mode 100644 index 9dbeb3941..000000000 --- a/packages/protocol/contracts/uniswap/test/libraries/SafeMathUni.sol +++ /dev/null @@ -1,17 +0,0 @@ -pragma solidity ^0.5.13; - -// a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math) - -library SafeMathUni { - function add(uint256 x, uint256 y) internal pure returns (uint256 z) { - require((z = x + y) >= x, "ds-math-add-overflow"); - } - - function sub(uint256 x, uint256 y) internal pure returns (uint256 z) { - require((z = x - y) <= x, "ds-math-sub-underflow"); - } - - function mul(uint256 x, uint256 y) internal pure returns (uint256 z) { - require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow"); - } -} diff --git a/packages/protocol/contracts/uniswap/test/libraries/TransferHelper.sol b/packages/protocol/contracts/uniswap/test/libraries/TransferHelper.sol deleted file mode 100644 index 0ee72d5ad..000000000 --- a/packages/protocol/contracts/uniswap/test/libraries/TransferHelper.sol +++ /dev/null @@ -1,44 +0,0 @@ -pragma solidity ^0.5.13; - -// SPDX-License-Identifier: GPL-3.0-or-later - -// Lines with line with a comment `CHANGED` was changed from original -// implementation to make it compatible with Solidity 0.5. -// As this is a mock, security is not a concern. - -// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false -library TransferHelper { - function safeApprove(address token, address to, uint256 value) internal { - // bytes4(keccak256(bytes('approve(address,uint256)'))); - (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value)); - require( - success && (data.length == 0 || abi.decode(data, (bool))), - "TransferHelper::safeApprove: approve failed" - ); - } - - function safeTransfer(address token, address to, uint256 value) internal { - // bytes4(keccak256(bytes('transfer(address,uint256)'))); - (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value)); - require( - success && (data.length == 0 || abi.decode(data, (bool))), - "TransferHelper::safeTransfer: transfer failed" - ); - } - - function safeTransferFrom(address token, address from, address to, uint256 value) internal { - // bytes4(keccak256(bytes('transferFrom(address,address,uint256)'))); - (bool success, bytes memory data) = token.call( - abi.encodeWithSelector(0x23b872dd, from, to, value) - ); - require( - success && (data.length == 0 || abi.decode(data, (bool))), - "TransferHelper::transferFrom: transferFrom failed" - ); - } - - function safeTransferETH(address to, uint256 value) internal { - // (bool success, ) = to.call{value: value}(new bytes(0)); // CHANGED - // require(success, 'TransferHelper::safeTransferETH: ETH transfer failed'); // CHANGED - } -} diff --git a/packages/protocol/contracts/uniswap/test/libraries/UQ112x112.sol b/packages/protocol/contracts/uniswap/test/libraries/UQ112x112.sol deleted file mode 100644 index 6ca901389..000000000 --- a/packages/protocol/contracts/uniswap/test/libraries/UQ112x112.sol +++ /dev/null @@ -1,20 +0,0 @@ -pragma solidity ^0.5.13; - -// a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format)) - -// range: [0, 2**112 - 1] -// resolution: 1 / 2**112 - -library UQ112x112 { - uint224 constant Q112 = 2**112; - - // encode a uint112 as a UQ112x112 - function encode(uint112 y) internal pure returns (uint224 z) { - z = uint224(y) * Q112; // never overflows - } - - // divide a UQ112x112 by a uint112, returning a UQ112x112 - function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) { - z = x / uint224(y); - } -} diff --git a/packages/protocol/contracts/uniswap/test/libraries/UniswapV2Library.sol b/packages/protocol/contracts/uniswap/test/libraries/UniswapV2Library.sol deleted file mode 100644 index d2f6400c2..000000000 --- a/packages/protocol/contracts/uniswap/test/libraries/UniswapV2Library.sol +++ /dev/null @@ -1,137 +0,0 @@ -pragma solidity ^0.5.13; - -import "../../interfaces/IUniswapV2Pair.sol"; - -import "./SafeMathUni.sol"; - -library UniswapV2Library { - using SafeMathUni for uint256; - - // returns sorted token addresses, used to handle return values from pairs sorted in this order - function sortTokens(address tokenA, address tokenB) - internal - pure - returns (address token0, address token1) - { - require(tokenA != tokenB, "UniswapV2Library: IDENTICAL_ADDRESSES"); - (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); - require(token0 != address(0), "UniswapV2Library: ZERO_ADDRESS"); - } - - // calculates the CREATE2 address for a pair without making any external calls - function pairFor(address factory, address tokenA, address tokenB, bytes32 initCodePairHash) - internal - pure - returns (address pair) - { - (address token0, address token1) = sortTokens(tokenA, tokenB); - pair = address( - uint256( - keccak256( - abi.encodePacked( - hex"ff", - factory, - keccak256(abi.encodePacked(token0, token1)), - initCodePairHash - ) - ) - ) - ); - } - - // fetches and sorts the reserves for a pair - function getReserves(address factory, address tokenA, address tokenB, bytes32 initCodePairHash) - internal - view - returns (uint256 reserveA, uint256 reserveB) - { - (address token0, ) = sortTokens(tokenA, tokenB); - - // require(false, "revert here"); - (uint256 reserve0, uint256 reserve1, ) = IUniswapV2Pair( - pairFor(factory, tokenA, tokenB, initCodePairHash) - ) - .getReserves(); - (reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0); - } - - // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset - function quote(uint256 amountA, uint256 reserveA, uint256 reserveB) - internal - pure - returns (uint256 amountB) - { - require(amountA > 0, "UniswapV2Library: INSUFFICIENT_AMOUNT"); - require(reserveA > 0 && reserveB > 0, "UniswapV2Library: INSUFFICIENT_LIQUIDITY"); - amountB = amountA.mul(reserveB) / reserveA; - } - - // given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset - function getAmountOut(uint256 amountIn, uint256 reserveIn, uint256 reserveOut) - internal - pure - returns (uint256 amountOut) - { - require(amountIn > 0, "UniswapV2Library: INSUFFICIENT_INPUT_AMOUNT"); - require(reserveIn > 0 && reserveOut > 0, "UniswapV2Library: INSUFFICIENT_LIQUIDITY"); - uint256 amountInWithFee = amountIn.mul(997); - uint256 numerator = amountInWithFee.mul(reserveOut); - uint256 denominator = reserveIn.mul(1000).add(amountInWithFee); - amountOut = numerator / denominator; - } - - // given an output amount of an asset and pair reserves, returns a required input amount of the other asset - function getAmountIn(uint256 amountOut, uint256 reserveIn, uint256 reserveOut) - internal - pure - returns (uint256 amountIn) - { - require(amountOut > 0, "UniswapV2Library: INSUFFICIENT_OUTPUT_AMOUNT"); - require(reserveIn > 0 && reserveOut > 0, "UniswapV2Library: INSUFFICIENT_LIQUIDITY"); - uint256 numerator = reserveIn.mul(amountOut).mul(1000); - uint256 denominator = reserveOut.sub(amountOut).mul(997); - amountIn = (numerator / denominator).add(1); - } - - // performs chained getAmountOut calculations on any number of pairs - function getAmountsOut( - address factory, - uint256 amountIn, - address[] memory path, - bytes32 initCodePairHash - ) internal view returns (uint256[] memory amounts) { - require(path.length >= 2, "UniswapV2Library: INVALID_PATH"); - amounts = new uint256[](path.length); - amounts[0] = amountIn; - for (uint256 i; i < path.length - 1; i++) { - (uint256 reserveIn, uint256 reserveOut) = getReserves( - factory, - path[i], - path[i + 1], - initCodePairHash - ); - amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut); - } - } - - // performs chained getAmountIn calculations on any number of pairs - function getAmountsIn( - address factory, - uint256 amountOut, - address[] memory path, - bytes32 initCodePairHash - ) internal view returns (uint256[] memory amounts) { - require(path.length >= 2, "UniswapV2Library: INVALID_PATH"); - amounts = new uint256[](path.length); - amounts[amounts.length - 1] = amountOut; - for (uint256 i = path.length - 1; i > 0; i--) { - (uint256 reserveIn, uint256 reserveOut) = getReserves( - factory, - path[i - 1], - path[i], - initCodePairHash - ); - amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut); - } - } -} diff --git a/packages/protocol/example-initialize-data.json b/packages/protocol/example-initialize-data.json deleted file mode 100644 index 54db748fb..000000000 --- a/packages/protocol/example-initialize-data.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "DowntimeSlasher": ["0x000000000000000000000000000000000000ce10", 20, 10, 10] -} diff --git a/packages/protocol/foundry.toml b/packages/protocol/foundry.toml deleted file mode 100644 index 4ea48658d..000000000 --- a/packages/protocol/foundry.toml +++ /dev/null @@ -1,20 +0,0 @@ -[profile.default] -src = 'contracts' -out = 'out' -test = 'test-sol' -libs = ['lib', 'node_modules'] -remappings = [ - 'openzeppelin-solidity/=lib/openzeppelin-contracts/', - 'solidity-bytes-utils/=lib/solidity-bytes-utils/', - 'forge-std/=lib/celo-foundry/lib/forge-std/src/', - 'ds-test/=lib/celo-foundry/lib/forge-std/lib/ds-test/src/', - 'celo-foundry/=lib/celo-foundry/src/', - '@summa-tx/memview.sol/=lib/memview.sol', -] - -no_match_contract = "RandomTest" -no_match_path = "contracts/common/libraries/test/BLS12Passthrough.sol" # tested from celo-blockain repo - -fs_permissions = [{ access = "read", path = "./out"}] - -# See more config options https://github.com/foundry-rs/foundry/tree/master/config diff --git a/packages/protocol/governanceConstitution.js b/packages/protocol/governanceConstitution.js deleted file mode 100644 index 601bda358..000000000 --- a/packages/protocol/governanceConstitution.js +++ /dev/null @@ -1,230 +0,0 @@ -contractPackages = require('./contractPackages.js') - -const MENTO_PACKAGE = contractPackages.MENTO_PACKAGE -// __contractPackage field is used to specify which contract package this contract belongs to -// leaving it undefined assumes it's a monorepo contract - -const DefaultConstitution = { - Accounts: { - default: 0.6, - }, - Attestations: { - default: 0.6, - setRegistry: 0.9, - setAttestationRequestFee: 0.6, - setAttestationExpiryBlocks: 0.6, - setSelectIssuersWaitBlocks: 0.6, - }, - BlockchainParameters: { - default: 0.9, - setBlockGasLimit: 0.8, - setIntrinsicGasForAlternativeFeeCurrency: 0.8, - }, - DoubleSigningSlasher: { - default: 0.7, - setSlashingIncentives: 0.7, - }, - DowntimeSlasher: { - default: 0.7, - setSlashingIncentives: 0.7, - setSlashableDowntime: 0.7, - }, - Election: { - default: 0.8, - setRegistry: 0.9, - setElectableValidators: 0.8, - setMaxNumGroupsVotedFor: 0.8, - setElectabilityThreshold: 0.8, - }, - EpochRewards: { - default: 0.8, - setRegistry: 0.9, - setCommunityRewardFraction: 0.8, - setTargetVotingGoldFraction: 0.8, - setTargetValidatorEpochPayment: 0.8, - setRewardsMultiplierParameters: 0.8, - setTargetVotingYieldParameters: 0.8, - }, - Escrow: { - default: 0.6, - addDefaultTrustedIssuer: 0.6, - removeDefaultTrustedIssuer: 0.6, - }, - FederatedAttestations: { - default: 0.6, - }, - FeeCurrencyWhitelist: { - default: 0.8, - addToken: 0.8, - }, - Freezer: { - default: 0.6, - freeze: 0.6, - unfreeze: 0.6, - }, - GasPriceMinimum: { - default: 0.7, - setRegistry: 0.9, - setAdjustmentSpeed: 0.7, - setTargetDensity: 0.7, - setGasPriceMinimumFloor: 0.7, - __contractPackage: contractPackages.SOLIDITY_08_PACKAGE, - }, - GoldToken: { - default: 0.9, - transfer: 0.6, - transferWithComment: 0.6, - approve: 0.6, - }, - Governance: { - default: 0.9, - setRegistry: 0.9, - setApprover: 0.9, - setConcurrentProposals: 0.9, - setMinDeposit: 0.9, - setQueueExpiry: 0.9, - setDequeueFrequency: 0.9, - setReferendumStageDuration: 0.9, - setExecutionStageDuration: 0.9, - setParticipationBaseline: 0.9, - setParticipationFloor: 0.9, - setBaselineUpdateFactor: 0.9, - setBaselineQuorumFactor: 0.9, - setConstitution: 0.9, - }, - GovernanceSlasher: { - default: 0.7, - approveSlashing: 0.7, - }, - LockedGold: { - default: 0.9, - setRegistry: 0.9, - setUnlockingPeriod: 0.8, - addSlasher: 0.9, - removeSlasher: 0.8, - }, - OdisPayments: { - default: 0.6, - }, - // Values for all proxied contracts. - proxy: { - _transferOwnership: 0.9, - _setAndInitializeImplementation: 0.9, - _setImplementation: 0.9, - }, - Random: { - default: 0.7, - setRandomnessBlockRetentionWindow: 0.7, - }, - Registry: { - default: 0.9, - setAddressFor: 0.9, - }, - SortedOracles: { - default: 0.7, - setReportExpiry: 0.7, - addOracle: 0.8, - removeOracle: 0.7, - }, - Validators: { - default: 0.7, - setRegistry: 0.9, - setMaxGroupSize: 0.7, - setMembershipHistoryLength: 0.7, - setGroupLockedGoldRequirements: 0.8, - setValidatorLockedGoldRequirements: 0.8, - setSlashingMultiplierResetPeriod: 0.7, - setValidatorScoreParameters: 0.7, - }, -} - -const constitutionExternal = { - Reserve: { - default: 0.9, - setRegistry: 0.9, - setTobinTaxStalenessThreshold: 0.7, - setDailySpendingRatio: 0.9, - setAssetAllocations: 0.7, - addToken: 0.9, - removeToken: 0.9, - addOtherReserveAddress: 0.9, - removeOtherReserveAddress: 0.9, - addSpender: 0.9, - removeSpender: 0.8, - addExchangeSpender: 0.9, - removeExchangeSpender: 0.9, - __contractPackage: MENTO_PACKAGE, - }, - StableToken: { - default: 0.8, - setRegistry: 0.9, - setInflationParameters: 0.9, - transfer: 0.6, - transferWithComment: 0.6, - approve: 0.6, - __contractPackage: MENTO_PACKAGE, - }, - StableTokenEUR: { - default: 0.8, - setRegistry: 0.9, - setInflationParameters: 0.9, - transfer: 0.6, - transferWithComment: 0.6, - approve: 0.6, - __contractPackage: MENTO_PACKAGE, - }, - StableTokenBRL: { - default: 0.8, - setRegistry: 0.9, - setInflationParameters: 0.9, - transfer: 0.6, - transferWithComment: 0.6, - approve: 0.6, - __contractPackage: MENTO_PACKAGE, - }, - GrandaMento: { - default: 0.8, - cancelExchangeProposal: 0.6, - setApprover: 0.8, - setSpread: 0.8, - setStableTokenExchangeLimits: 0.8, - setVetoPeriodSeconds: 0.8, - __contractPackage: MENTO_PACKAGE, - }, - Exchange: { - default: 0.8, - setRegistry: 0.9, - setUpdateFrequency: 0.8, - setMinimumReports: 0.8, - setStableToken: 0.8, - setSpread: 0.8, - setReserveFraction: 0.8, - __contractPackage: MENTO_PACKAGE, - }, - ExchangeEUR: { - default: 0.8, - setRegistry: 0.9, - setUpdateFrequency: 0.8, - setMinimumReports: 0.8, - setStableToken: 0.8, - setSpread: 0.8, - setReserveFraction: 0.8, - __contractPackage: MENTO_PACKAGE, - }, - ExchangeBRL: { - default: 0.8, - setRegistry: 0.9, - setUpdateFrequency: 0.8, - setMinimumReports: 0.8, - setStableToken: 0.8, - setSpread: 0.8, - setReserveFraction: 0.8, - __contractPackage: MENTO_PACKAGE, - }, -} - -const constitution = { ...DefaultConstitution, ...constitutionExternal } - -module.exports = { - constitution, -} diff --git a/packages/protocol/index.d.ts b/packages/protocol/index.d.ts deleted file mode 100644 index 811c07309..000000000 --- a/packages/protocol/index.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module 'eth-lib' diff --git a/packages/protocol/lib/artifactsSingleton.ts b/packages/protocol/lib/artifactsSingleton.ts deleted file mode 100644 index 3d4754318..000000000 --- a/packages/protocol/lib/artifactsSingleton.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { ContractPackage } from '../contractPackages'; - -// Defines a minimal interface an artifact should implement -export interface ArtifactSet { - require(key: string): any; - getProxy(key: string): any; -} - -function getProxyName(contractName:string){ - return contractName + "Proxy"; -} - -// This class is meant to be used to wrap truffle artifacts -// and extend its interface. -// ArtifactsSingleton.wrap returns an instance of DefaultArtifact -export class DefaultArtifact implements ArtifactSet{ - public artifacts: any - - public constructor(artifacts) { - this.artifacts = artifacts - } - - public require(key: string) { - return this.artifacts.require(key) - } - - public getProxy(key: string) { - return this.require(getProxyName(key)) - } - -} - -// This objects replicates a Truffle `artifacts.require` singleton -// but constructed manually -export class ArtifactsSingleton implements ArtifactSet{ - public static setNetwork(network: any) { - this.network = network - } - - public static getNetwork() { - return this.network - } - - public static getInstance(contractPackage: ContractPackage, defaultArtifacts?: any): any { - if (contractPackage === undefined || contractPackage.path === undefined) { - // default artifacts but overcharged with a getProxy method - const artifacts = new DefaultArtifact(defaultArtifacts) - return artifacts - } - - const namespace = contractPackage.path - if (!(namespace in ArtifactsSingleton.instances)) { - ArtifactsSingleton.instances[namespace] = new ArtifactsSingleton() - } - - return ArtifactsSingleton.instances[namespace] - } - - public static wrap(artifacts:any){ - if (artifacts instanceof ArtifactsSingleton || artifacts instanceof DefaultArtifact){ - return artifacts - } - - return new DefaultArtifact(artifacts) - } - - private static instances: { [key: string]: ArtifactsSingleton } = {} - - private static network: any - - public artifacts: { [key: string]: any } = {} - - private constructor() {} - - public addArtifact(key: string, value: any) { - this.artifacts[key] = value - } - - public require(key: string) { - return this.artifacts[key] - } - - public getProxy(key: string, defaultArtifacts?:any) { - const proxyArtifactName = getProxyName(key) - - const toReturn = this.require(proxyArtifactName) - - if (toReturn === undefined){ - // in case the package of this artifact has proxiesPath set - // this needs to be changed to support it, now only "/" path is supported - return defaultArtifacts?.require(proxyArtifactName) - } - - return toReturn - } -} diff --git a/packages/protocol/lib/bytecode.ts b/packages/protocol/lib/bytecode.ts deleted file mode 100644 index 17ca22721..000000000 --- a/packages/protocol/lib/bytecode.ts +++ /dev/null @@ -1,140 +0,0 @@ -// tslint:disable: max-classes-per-file -/* - * The Solidity compiler appends a Swarm Hash of compilation metadata to the end - * of bytecode. We find this hash based on the specification here: - * https://solidity.readthedocs.io/en/develop/metadata.html#encoding-of-the-metadata-hash-in-the-bytecode - */ - -import { NULL_ADDRESS, trimLeading0x } from '@celo/base/lib/address' - -const CONTRACT_METADATA_REGEXPS = [ - // 0.5.8 - 'a165627a7a72305820.{64}0029', - // 0.5.13 - 'a265627a7a72315820.{64}64736f6c6343.{6}0032', - // 0.8.19 - 'a264697066735822.{68}64736f6c6343.{6}0033' -] - -const GENERAL_METADATA_REGEXP = new RegExp( - `^(.*)(${CONTRACT_METADATA_REGEXPS.map((r) => '(' + r + ')').join('|')})$`, - 'i' // Use i flag to make search case insensitive. -) - -export const stripMetadata = (bytecode: string): string => { - if (bytecode === '0x') { - return '0x' - } - - const match = bytecode.match(GENERAL_METADATA_REGEXP) - if (match === null) { - throw new Error( - 'Only support stripping metadata from bytecodes generated by solc up to v0.5.13 with no experimental features.' - ) - } - return match[1] -} - -// Maps library names to their onchain addresses (formatted without "0x" prefix). -export interface LibraryLinks { - [name: string]: string -} - -/* - * Unresolved libraries appear as "__LibraryName___..." in bytecode output by - * solc. The length of the entire string is 40 characters (accounting for the 20 - * bytes of the address that should be substituted in). - */ -const padForLink = (name: string): string => { - return `__${name}`.padEnd(40, '_') -} - -export const linkLibraries = (bytecode: string, libraryLinks: LibraryLinks): string => { - Object.keys(libraryLinks).forEach((libraryName) => { - const linkString = padForLink(libraryName) - // Use g flag to iterate through for all occurences. - bytecode = bytecode.replace(RegExp(linkString, 'g'), libraryLinks[libraryName]) - }) - - return bytecode -} - -const ADDRESS_LENGTH = 40 -const PUSH20_OPCODE = '73' -// To check that a library isn't being called directly, the Solidity -// compiler starts a library's bytecode with a comparison of the current -// address with the address the library was deployed to (it has to differ -// to ensure the library is being called with CALLCODE or DELEGATECALL -// instead of a regular CALL). -// The address is only known at contract construction time, so -// the compiler's output contains a placeholder 0-address, while the onchain -// bytecode has the correct address inserted. -// Reference: https://solidity.readthedocs.io/en/v0.5.12/contracts.html#call-protection-for-libraries -export const verifyAndStripLibraryPrefix = (bytecode: string, address = NULL_ADDRESS) => { - if (bytecode.slice(2, 4) !== PUSH20_OPCODE) { - throw new Error(`Library bytecode doesn't start with address load`) - } else if (bytecode.slice(4, 4 + ADDRESS_LENGTH) !== trimLeading0x(address).toLowerCase()) { - throw new Error(`Library bytecode loads unexpected address at start`) - } - - return bytecode.slice(4 + ADDRESS_LENGTH, bytecode.length) -} - -export class LibraryPositions { - static libraryLinkRegExpString = '__([A-Z][A-Za-z0-9]*)_{2,}' - - positions: { [library: string]: number[] } - - /* - * Creates a LibraryPositions object, which, for each yet to be linked library, - * contains the bytecode offsets of where the library address should be - * inserted. - */ - constructor(bytecode: string) { - this.positions = {} - // Use g flag to iterate through for all occurences. - const libraryLinkRegExp = new RegExp(LibraryPositions.libraryLinkRegExpString, 'g') - let match = libraryLinkRegExp.exec(bytecode) - while (match != null) { - // The first capture group is the library's name - this.addPosition(match[1], match.index) - match = libraryLinkRegExp.exec(bytecode) - } - } - - private addPosition(library: string, position: number) { - if (!this.positions[library]) { - this.positions[library] = [] - } - - this.positions[library].push(position) - } -} - -export class LibraryAddresses { - addresses: { [library: string]: string } - - constructor() { - this.addresses = {} - } - - collect = (bytecode: string, libraryPositions: LibraryPositions) => - Object.keys(libraryPositions.positions).forEach((library) => - libraryPositions.positions[library].forEach((position) => { - if (!this.addAddress(library, bytecode.slice(position, position + ADDRESS_LENGTH))) { - throw new Error(`Mismatched addresses for ${library} at ${position}`) - } - }) - ) - - /* - * Tries to add a library name -> address mapping. If the library has already - * had an address added, checks that the new address matches the old one. - */ - private addAddress(library: string, address: string): boolean { - if (!this.addresses[library]) { - this.addresses[library] = address - } - return this.addresses[library] === address - } -} diff --git a/packages/protocol/lib/celo-foundry b/packages/protocol/lib/celo-foundry deleted file mode 160000 index e83579392..000000000 --- a/packages/protocol/lib/celo-foundry +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e835793925bfaaa8ef7aa8d341a2256c29470731 diff --git a/packages/protocol/lib/compatibility/ast-code.ts b/packages/protocol/lib/compatibility/ast-code.ts deleted file mode 100644 index 7c6bef1bf..000000000 --- a/packages/protocol/lib/compatibility/ast-code.ts +++ /dev/null @@ -1,271 +0,0 @@ -import { stripMetadata } from '@celo/protocol/lib/bytecode' -import { - Change, - ContractKindChange, DeployedBytecodeChange, MethodAddedChange, - MethodMutabilityChange, MethodRemovedChange, MethodReturnChange, - MethodVisibilityChange, NewContractChange -} from '@celo/protocol/lib/compatibility/change' -import { makeZContract } from '@celo/protocol/lib/compatibility/internal' -import { - BuildArtifacts, - Contract as ZContract -} from '@openzeppelin/upgrades' -import ContractAST from '@openzeppelin/upgrades/lib/utils/ContractAST' - -export enum Visibility { - NONE = "", - EXTERNAL = "external", - PUBLIC = "public", - INTERNAL = "internal", - PRIVATE = "private" -} - -export enum Mutability { - NONE = "", - PURE = "pure", - VIEW = "view", - PAYABLE = "payable" -} - -enum StorageLocation { - NONE = "", - // Default gets replaced to None when comparing parameter storage locations - DEFAULT = "default", - - STORAGE = "storage", - MEMORY = "memory", - CALLDATA = "calldata", -} - -const CONTRACT_KIND_CONTRACT = 'contract' -const OUT_VOID_PARAMETER_STRING = 'void' - -/** - * A compatibility report with all the detected changes from two compiled - * contract folders. - */ -export class ASTCodeCompatibilityReport { - constructor(private readonly changes: Change[]) {} - push(...changes: Change[]) { - this.changes.push(...changes) - } - include(other: ASTCodeCompatibilityReport) { - this.push(...other.changes) - } - getChanges = (): Change[] => { - return this.changes - } -} - -// Types used by the Method interface -// OpenZep uses 'any' for methods so we -// define our own here - -interface TypeDescriptions { - typeString: string -} - -interface Parameter { - storageLocation: StorageLocation - typeDescriptions: TypeDescriptions -} - -interface Parameters { - parameters: Parameter[] -} - -interface Method { - selector: string - visibility: Visibility - stateMutability: Mutability - parameters: Parameters - returnParameters: Parameters -} - -// Implementation - -function getSignature(method: Method): string { - // This is used as the ID of a method - return method.selector -} - -interface MethodIndex { - [signature: string]: Method; -} - -/** - * @returns A method index where {key: signature => value: method} - */ -function createMethodIndex(methods: Method[]): MethodIndex { - const asPairs = methods.map(m => ({ [`${getSignature(m)}`]: m })) - return Object.assign({}, ...asPairs) -} - -function mergeReports(reports: ASTCodeCompatibilityReport[]): ASTCodeCompatibilityReport{ - const report = new ASTCodeCompatibilityReport([]) - reports.forEach((r: ASTCodeCompatibilityReport): void => { - report.include(r) - }) - return report -} - -function parametersSignature(parameters: Parameter[]): string { - if (parameters.length === 0) { - return OUT_VOID_PARAMETER_STRING - } - const singleSignature = (p: Parameter): string => { - const storage = p.storageLocation === StorageLocation.DEFAULT ? StorageLocation.NONE : `${p.storageLocation} ` - return `${storage}${p.typeDescriptions.typeString}` - } - return parameters.map(singleSignature).join(', ') -} - - -function checkMethodCompatibility(contract: string, m1: Method, m2: Method): ASTCodeCompatibilityReport { - const report = new ASTCodeCompatibilityReport([]) - const signature = getSignature(m1) - // Sanity check - const signature2 = getSignature(m2) - if (signature !== signature2) { - throw new Error(`Signatures should be equal: ${signature} !== ${signature2}`) - } - // Visibility changes - if (m1.visibility !== m2.visibility) { - report.push(new MethodVisibilityChange(contract, signature, m1.visibility, m2.visibility)) - } - - // Return parameter changes - const ret1 = parametersSignature(m1.returnParameters.parameters) - const ret2 = parametersSignature(m2.returnParameters.parameters) - if (ret1 !== ret2) { - report.push(new MethodReturnChange(contract, signature, ret1, ret2)) - } - - // State mutability changes - const state1 = m1.stateMutability - const state2 = m2.stateMutability - if (state1 !== state2) { - report.push(new MethodMutabilityChange(contract, signature, state1, state2)) - } - return report -} - -const getCheckableMethodsFromAST = (contract: ContractAST, id: string): any[] => { - const checkableMethods = (method: Method) => method.visibility === Visibility.EXTERNAL || method.visibility === Visibility.PUBLIC - try { - return contract.getMethods().filter(checkableMethods) - } catch (error) { - throw { - message: `Error in the @openzeppelin/.../ContractAST.getMethods() for the artifacts in the '${id}' folder. - Most likely this is due to a botched build, or a build on a non-cleaned folder.`, - error - } - } -} - -function doASTCompatibilityReport( - contractName: string, - oldAST: ContractAST, - newAST: ContractAST): ASTCodeCompatibilityReport { - const oldMethods = createMethodIndex(getCheckableMethodsFromAST(oldAST, 'old')) - const newMethods = createMethodIndex(getCheckableMethodsFromAST(newAST, 'new')) - - const report = new ASTCodeCompatibilityReport([]) - - // Check for modified or missing methods in the new version - Object.keys(oldMethods).forEach((signature: string) => { - const method: Method = oldMethods[signature] - if (!newMethods.hasOwnProperty(signature)) { - // Method deleted, major change - report.push(new MethodRemovedChange(contractName, signature)) - // Continue - return - } - const newMethod: Method = newMethods[signature] - report.include(checkMethodCompatibility(contractName, method, newMethod)) - }) - // Check for added methods in the new version - Object.keys(newMethods).forEach((signature: string) => { - if (!oldMethods.hasOwnProperty(signature)) { - // New method, minor change - report.push(new MethodAddedChange(contractName, signature)) - } - }) - return report -} - -function generateASTCompatibilityReport(oldContract: ZContract, oldArtifacts: BuildArtifacts, - newContract: ZContract, newArtifacts: BuildArtifacts): ASTCodeCompatibilityReport { - // Sanity checks - if (newContract === null) { - throw new Error('newContract cannot be null') - } - if (oldArtifacts === null) { - throw new Error('oldArtifacts cannot be null') - } - if (newArtifacts === null) { - throw new Error('newArtifacts cannot be null') - } - const contractName = newContract.schema.contractName - - // Need to manually use ContractAST since its internal use in ZContract - // does not pass the artifacts parameter to the constructor, therefore - // forcing a reloading of BuildArtifacts. - const newAST = new ContractAST(newContract, newArtifacts) - const newKind = newAST.getContractNode().contractKind - if (oldContract === null) { - if (newKind === CONTRACT_KIND_CONTRACT) { - return new ASTCodeCompatibilityReport([new NewContractChange(contractName)]) - } else { - // New contract added of a non-contract kind (library/interface) - // therefore no functionality added - return new ASTCodeCompatibilityReport([]) - } - } - - // Name sanity check - if (oldContract.schema.contractName !== contractName) { - throw new Error(`Contract names should be equal: ${oldContract.schema.contractName} !== ${contractName}`) - } - - const oldAST = new ContractAST(oldContract, oldArtifacts) - const oldKind = oldAST.getContractNode().contractKind - if (oldKind !== newKind) { - // different contract kind (library/interface/contract) - return new ASTCodeCompatibilityReport([new ContractKindChange(contractName, oldKind, newKind)]) - } - - const report = doASTCompatibilityReport(contractName, oldAST, newAST) - // Check deployed byte code change - if (stripMetadata(oldContract.schema.deployedBytecode) !== stripMetadata(newContract.schema.deployedBytecode)) { - report.push(new DeployedBytecodeChange(contractName)) - } - return report -} - -/** - * Runs an ast code comparison and returns the spotted changes from the built artifacts given. - * - * @param oldArtifacts - * @param newArtifacts - */ -export function reportASTIncompatibilities( - // oldArtifacts also needs to be a set - // https://github.com/celo-org/celo-monorepo/issues/10567 - oldArtifacts: BuildArtifacts, - newArtifactsSets: BuildArtifacts[]): ASTCodeCompatibilityReport { - - let out: ASTCodeCompatibilityReport[] = [] - for (const newArtifacts of newArtifactsSets) { - const reports = newArtifacts.listArtifacts() - .map((newArtifact) => { - const oldArtifact = oldArtifacts.getArtifactByName(newArtifact.contractName) - const oldZContract = oldArtifact ? makeZContract(oldArtifact) : null - return generateASTCompatibilityReport(oldZContract, oldArtifacts, makeZContract(newArtifact), newArtifacts) - }) - out = [...out, ...reports] - - } - - return mergeReports(out) -} diff --git a/packages/protocol/lib/compatibility/ast-layout.ts b/packages/protocol/lib/compatibility/ast-layout.ts deleted file mode 100644 index 28cc3dee8..000000000 --- a/packages/protocol/lib/compatibility/ast-layout.ts +++ /dev/null @@ -1,231 +0,0 @@ -import { Contract as Web3Contract } from '@celo/connect'; -import { Artifact, TypeInfo } from '@celo/protocol/lib/compatibility/internal'; -import { - BuildArtifacts, - Operation, - StorageLayoutInfo, - Contract as ZContract, - compareStorageLayouts, - getStorageLayout -} from '@openzeppelin/upgrades'; -const Web3 = require('web3') - -const web3 = new Web3(null) - -// getStorageLayout needs an oz-sdk Contract class instance. This class is a -// subclass of Contract from web3-eth-contract, with an added .schema member and -// several methods. -// -// Couldn't find an easy way of getting one just from contract artifacts. But -// for getStorageLayout we really only need .schema.ast and .schema.contractName. -const addSchemaForLayoutChecking = (web3Contract: Web3Contract, artifact: any): ZContract => { - // @ts-ignore - const contract = web3Contract as Contract - // @ts-ignore - contract.schema = {} - contract.schema.ast = artifact.ast - contract.schema.contractName = artifact.contractName - return contract -} - -const makeZContract = (artifact: any): ZContract => { - const contract = new web3.eth.Contract(artifact.abi) - - return addSchemaForLayoutChecking(contract, artifact) -} - -export const getLayout = (artifact: Artifact, artifacts: BuildArtifacts) => { - const contract = makeZContract(artifact) - - return getStorageLayout(contract, artifacts) -} - -const selectIncompatibleOperations = (diff: Operation[]) => - diff.filter(operation => operation.action !== 'append' - && !(operation.action === 'rename' && (`deprecated_${operation.original.label}` === operation.updated.label && operation.original.type === operation.updated.type))) - -export interface ASTStorageCompatibilityReport { - contract: string - compatible: boolean - errors: string[] - expanded?: boolean -} - -const operationToDescription = (operation: Operation) => { - let message: string - - const updated = operation.updated - const original = operation.original - - switch (operation.action) { - case 'typechange': - message = `variable ${updated.label} had type ${original.type}, now has type ${updated.type}` - break - case 'insert': - message = `variable ${updated.label} was inserted` - break - case 'pop': - message = `variable ${original.label} was removed` - break - case 'delete': - message = `variable ${original.label} was removed` - break - case 'rename': - message = `variable ${updated.label} was renamed from ${original.label}` - break - case 'replace': - message = `variable ${updated.label} was replaced from ${original.label}` - break - case 'append': - message = `variable ${updated.label} was appended` - - default: - message = `unknown operation ${operation.action}` - } - - return message -} - -const generateLayoutCompatibilityReport = (oldLayout: StorageLayoutInfo, newLayout: StorageLayoutInfo) => { - const diff = compareStorageLayouts(oldLayout, newLayout) - const incompatibilities = selectIncompatibleOperations(diff) - if (incompatibilities.length === 0) { - return { - compatible: true, - errors: [] - } - } else { - return { - compatible: false, - errors: incompatibilities.map(operationToDescription) - } - } -} - -const compareStructDefinitions = (oldType: TypeInfo, newType: TypeInfo, structExpandable: boolean) => { - if (oldType.kind !== 'struct') { - return { - same: false, - errors: [`${newType.label} wasn't a struct type, now is`] - } - } - - if (structExpandable && oldType.members.length < newType.members.length) { - const expandableErrors = oldType.members.map((oldMember, i) => { - const newMember = newType.members[i] - - if (oldMember.label !== newMember.label && `deprecated_${oldMember.label}` !== newMember.label) { - return `struct ${newType.label} had ${oldMember.label} in slot ${i}, now has ${newMember.label}` - } - - if (oldMember.type !== newMember.type) { - return `struct ${newType.label}'s member ${newMember.label} changed type from ${oldMember.type} to ${newMember.type}` - } - }).filter(error => error) - - if (expandableErrors.length === 0) { - return { - same: true, - expanded: true, - errors: [] - } - } - } - - if (oldType.members.length !== newType.members.length) { - return { - same: false, - errors: [`struct ${newType.label} has changed members`] - } - } - - const memberErrors = newType.members.map((newMember, i) => { - const oldMember = oldType.members[i] - if (oldMember.label !== newMember.label && `deprecated_${oldMember.label}` !== newMember.label) { - return `struct ${newType.label} had ${oldMember.label} in slot ${i}, now has ${newMember.label}` - } - - if (oldMember.type !== newMember.type) { - return `struct ${newType.label}'s member ${newMember.label} changed type from ${oldMember.type} to ${newMember.type}` - } - - return '' - }).filter(error => error !== '') - - return { - same: memberErrors.length === 0, - errors: memberErrors - } -} - -// Struct is expandable only if used in mappings or arrays -const isStructExpandable = (oldType: TypeInfo, oldLayout: StorageLayoutInfo) => { - const structString = `t_struct<${oldType.label}>` - return !oldLayout.storage.some(storage => storage.type === structString) -} - -const generateStructsCompatibilityReport = (oldLayout: StorageLayoutInfo, newLayout: StorageLayoutInfo): {compatible: boolean, errors: any[], expanded?: boolean} => { - let compatible = true - let errors = [] - let expanded: boolean - - Object.keys(newLayout.types).forEach(typeName => { - const newType = newLayout.types[typeName] - const oldType = oldLayout.types[typeName] - - if (newType.kind === 'struct' && oldType !== undefined) { - const structExpandable = isStructExpandable(oldType, oldLayout) - const structReport = compareStructDefinitions(oldType, newType, structExpandable) - if (!structReport.same) { - compatible = false - errors = errors.concat(structReport.errors) - } - expanded = structReport.expanded - } - }) - - return { - compatible, - errors, - expanded - } -} - -export const generateCompatibilityReport = (oldArtifact: Artifact, oldArtifacts: BuildArtifacts, - newArtifact: Artifact, newArtifacts: BuildArtifacts) - : {contract: string, compatible: boolean, errors: any[], expanded?: boolean } => { - const oldLayout = getLayout(oldArtifact, oldArtifacts) - const newLayout = getLayout(newArtifact, newArtifacts) - const layoutReport = generateLayoutCompatibilityReport(oldLayout, newLayout) - const structsReport = generateStructsCompatibilityReport(oldLayout, newLayout) - - return { - contract: newArtifact.contractName, - compatible: layoutReport.compatible && structsReport.compatible, - errors: layoutReport.errors.concat(structsReport.errors), - expanded: structsReport.expanded - } -} - -export const reportLayoutIncompatibilities = (oldArtifacts: BuildArtifacts, newArtifactsSets: BuildArtifacts[]): ASTStorageCompatibilityReport[] => { - let out: ASTStorageCompatibilityReport[] = [] - for (const newArtifacts of newArtifactsSets) { - const reports = newArtifacts.listArtifacts().map((newArtifact) => { - const oldArtifact = oldArtifacts.getArtifactByName(newArtifact.contractName) - if (oldArtifact !== undefined) { - return generateCompatibilityReport(oldArtifact, oldArtifacts, newArtifact, newArtifacts) - } else { - // Generate an empty report for new contracts, which are, by definition, backwards - // compatible. - return { - contract: newArtifact.contractName, - compatible: true, - errors: [] - } - } - }) - - out = [...out, ...reports] - } - return out -} diff --git a/packages/protocol/lib/compatibility/ast-version.ts b/packages/protocol/lib/compatibility/ast-version.ts deleted file mode 100644 index db246bb92..000000000 --- a/packages/protocol/lib/compatibility/ast-version.ts +++ /dev/null @@ -1,106 +0,0 @@ -// tslint:disable: max-classes-per-file -import { Artifact } from '@celo/protocol/lib/compatibility/internal'; -import { ContractVersion, ContractVersionChecker, ContractVersionCheckerIndex, ContractVersionDelta, ContractVersionDeltaIndex, ContractVersionIndex, DEFAULT_VERSION_STRING } from '@celo/protocol/lib/compatibility/version'; -import { Address as EJSAddress } from "@ethereumjs/util"; -import { VM } from "@ethereumjs/vm"; -import { BuildArtifacts } from '@openzeppelin/upgrades'; -import { isLibrary } from './report'; -const abi = require('ethereumjs-abi') - -/** - * A mapping {contract name => {@link ContractVersion}}. - */ -export class ASTContractVersions { - static fromArtifacts = async (artifactsSet: BuildArtifacts[]): Promise=> { - const contracts = {} - - for (const artifacts of artifactsSet){ - await Promise.all(artifacts.listArtifacts().filter(c => !isLibrary(c.contractName, [artifacts])).map(async (artifact) => { - contracts[artifact.contractName] = await getContractVersion(artifact) - })) - } - - return new ASTContractVersions(contracts) - } - - constructor(public readonly contracts: ContractVersionIndex) {} -} - -/** - * Gets the version of a contract by calling Contract.getVersionNumber() on - * the contract deployed bytecode. - * - * If the contract version cannot be retrieved, returns version 1.1.0.0 by default. - */ -export async function getContractVersion(artifact: Artifact): Promise { - const vm = await VM.create(); - const bytecode = artifact.deployedBytecode - const data = '0x' + abi.methodID('getVersionNumber', []).toString('hex') - const nullAddress = '0000000000000000000000000000000000000000' - // Artificially link all libraries to the null address. - const linkedBytecode = bytecode.split(/[_]+[A-Za-z0-9]+[_]+/).join(nullAddress) - const result = await vm.evm.runCall({ - to:new EJSAddress(Buffer.from(nullAddress, 'hex')) , - caller: new EJSAddress(Buffer.from(nullAddress, 'hex')), - code: Buffer.from(linkedBytecode.slice(2), 'hex'), - isStatic: true, - data: Buffer.from(data.slice(2), 'hex') - }) - if (result.execResult.exceptionError === undefined) { - const value = result.execResult.returnValue - if (value.length === 4 * 32) { - return ContractVersion.fromGetVersionNumberReturnValue(value) - } - } - // If we can't fetch the version number, assume default version. - return ContractVersion.fromString(DEFAULT_VERSION_STRING) -} - -export class ASTContractVersionsChecker { - static create = async (oldArtifacts: BuildArtifacts, newArtifactsSet: BuildArtifacts[], expectedVersionDeltas: ContractVersionDeltaIndex): Promise => { - const oldVersions = await ASTContractVersions.fromArtifacts([oldArtifacts]) - const newVersions = await ASTContractVersions.fromArtifacts(newArtifactsSet) - const contracts = {} - Object.keys(newVersions.contracts).map((contract:string) => { - const versionDelta = expectedVersionDeltas[contract] === undefined ? ContractVersionDelta.fromChanges(false, false, false, false) : expectedVersionDeltas[contract] - const oldVersion = oldVersions.contracts[contract] === undefined ? null : oldVersions.contracts[contract] - contracts[contract] = new ContractVersionChecker(oldVersion, newVersions.contracts[contract], versionDelta) - }) - return new ASTContractVersionsChecker(contracts) - } - - constructor(public readonly contracts: ContractVersionCheckerIndex) {} - - /** - * @return a new {@link ASTContractVersionsChecker} with the same contracts - * excluding all those whose names match the {@param exclude} parameters. - */ - excluding = (exclude: RegExp): ASTContractVersionsChecker => { - const included = (contract: string): boolean => { - if (exclude != null) { - return !exclude.test(contract) - } - return true - } - const contracts = {} - Object.keys(this.contracts).filter(included).map((contract: string) => { - contracts[contract] = this.contracts[contract] - }) - return new ASTContractVersionsChecker(contracts) - } - - - public mismatches = () : ASTContractVersionsChecker => { - const mismatches = {} - Object.keys(this.contracts).map((contract: string) => { - if (!this.contracts[contract].matches()) { - mismatches[contract] = this.contracts[contract] - } - }) - return new ASTContractVersionsChecker(mismatches) - } - - public isEmpty = (): boolean => { - return Object.keys(this.contracts).length === 0 - } -} diff --git a/packages/protocol/lib/compatibility/categorizer.ts b/packages/protocol/lib/compatibility/categorizer.ts deleted file mode 100644 index c4cbac6e9..000000000 --- a/packages/protocol/lib/compatibility/categorizer.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { - Change, - ChangeVisitor, - ContractKindChange, DeployedBytecodeChange, LibraryLinkingChange, - MethodAddedChange, MethodMutabilityChange, MethodRemovedChange, - MethodReturnChange, MethodVisibilityChange, NewContractChange -} from '@celo/protocol/lib/compatibility/change' - -/** - * Change type categories according to semantic versioning standards - */ -export enum ChangeType { Patch, Minor, Major } - -/** - * @returns the assigned {@link ChangeType} for each {@link Change} - */ -export interface Categorizer extends ChangeVisitor {} - -/** - * @returns a mapping of {ChangeType => Change[]} according to the {@link categorizer} used - */ -export function categorize(changes: Change[], categorizer: Categorizer): Change[][] { - const byCategory = [] - for (const ct of Object.values(ChangeType)) { - byCategory[ct] = [] - } - changes.map(c => byCategory[c.accept(categorizer)].push(c)) - return byCategory -} - -/** - * Default implementation of {@link Categorizer}, where: - * Major: - * New contract, Mutability, Params, Return Params, Method Removed, Contract type changes - * Minor: - * Method Added - * Patch: - * Visibility, Bytecode (implementation) changes - */ -export class DefaultCategorizer implements Categorizer { - onNewContract = (_change: NewContractChange): ChangeType => ChangeType.Major - onMethodMutability = (_change: MethodMutabilityChange): ChangeType => ChangeType.Major - onMethodReturn = (_change: MethodReturnChange): ChangeType => ChangeType.Major - onMethodRemoved = (_change: MethodRemovedChange): ChangeType => ChangeType.Major - onContractKind = (_change: ContractKindChange): ChangeType => ChangeType.Major - - onMethodAdded = (_change: MethodAddedChange): ChangeType => ChangeType.Minor - // Changing between public and external visibility has no impact. - onMethodVisibility = (_change: MethodVisibilityChange): ChangeType => ChangeType.Patch - onDeployedBytecode = (_change: DeployedBytecodeChange): ChangeType => ChangeType.Patch - - onLibraryLinking = (_change: LibraryLinkingChange): ChangeType => ChangeType.Patch -} diff --git a/packages/protocol/lib/compatibility/change.ts b/packages/protocol/lib/compatibility/change.ts deleted file mode 100644 index 5409def93..000000000 --- a/packages/protocol/lib/compatibility/change.ts +++ /dev/null @@ -1,185 +0,0 @@ -// tslint:disable: max-classes-per-file -/** - * A code change detected from an old to a new version of a contract. - */ -export interface Change { - getContract(): string - accept(visitor: ChangeVisitor): T -} - -/** - * Visitor pattern implementation for the {@link Change} hierarchy. - */ -export interface ChangeVisitor { - onMethodMutability(change: MethodMutabilityChange): T - onMethodReturn(change: MethodReturnChange): T - onMethodVisibility(change: MethodVisibilityChange): T - onMethodAdded(change: MethodAddedChange): T - onMethodRemoved(change: MethodRemovedChange): T - onContractKind(change: ContractKindChange): T - onNewContract(change: NewContractChange): T - onDeployedBytecode(change: DeployedBytecodeChange): T - onLibraryLinking(change: LibraryLinkingChange): T -} - -/** - * Abstract implementation for the {@link Change} interface. - */ -abstract class ContractChange implements Change { - type: string - constructor(private readonly contract: string) { - this.contract = contract - } - getContract() { - return this.contract - } - - abstract accept(visitor: ChangeVisitor): T -} - -/** - * A 'New Contract' change detected during the compatibility report. A - * contract was found in the new folder that was not present in the old - * folder. The id which is used to do this comparison is the name of the - * contract, therefore not only adding a contract, but a name change - * would produce this change. - */ -export class NewContractChange extends ContractChange { - type = "NewContract" - accept(visitor: ChangeVisitor): T { - return visitor.onNewContract(this) - } -} - -/** - * Abstract class providing standard 'old value => new value' functionality - * for {@link ContractChange} - */ -abstract class ContractValueChange extends ContractChange { - constructor( - contract: string, - public readonly oldValue: string, - public readonly newValue: string) { - super(contract) - } -} - -/** - * The deployedBytecode field in the built json artifact has changed, with - * the exception of metadata, from the old folder to the new one. This is - * due to an implementation change. - * - * To avoid false positives, compile both old and new folders in the same - * full path. - */ -export class DeployedBytecodeChange extends ContractChange { - type = "DeployedBytecode" - accept(visitor: ChangeVisitor): T { - return visitor.onDeployedBytecode(this) - } -} - -/** - * The Kind of a contract changed. Kind examples are - * 'contract' or 'library'. - */ -export class ContractKindChange extends ContractValueChange { - type = "ContractKind" - accept(visitor: ChangeVisitor): T { - return visitor.onContractKind(this) - } -} - -/** - * Abstract implementation for the {@link Change} interface for - * method changes. - * - * Since we use the {@link signature} as the id of the method, it's - * the same value for the old and the new contract. - */ -abstract class MethodChange extends ContractChange { - constructor(contract: string, private readonly signature: string) { - super(contract) - } - getSignature() { - return this.signature - } -} - -/** - * A new method was found in the new version of the contract. - */ -export class MethodAddedChange extends MethodChange { - type = "MethodAdded" - accept(visitor: ChangeVisitor): T { - return visitor.onMethodAdded(this) - } -} - -/** - * A method from the old version is not present in the new version. - */ -export class MethodRemovedChange extends MethodChange { - type = "MethodRemoved" - accept(visitor: ChangeVisitor): T { - return visitor.onMethodRemoved(this) - } -} - -/** - * Abstract class providing standard 'old value => new value' functionality - * for {@link MethodChange} - */ -abstract class MethodValueChange extends MethodChange { - constructor(contract: string, signature: string, - public readonly oldValue: string, - public readonly newValue: string) { - super(contract, signature) - } -} - -/** - * The visibility (public/external) of a method changed. - */ -export class MethodVisibilityChange extends MethodValueChange { - type = "MethodVisibility" - accept(visitor: ChangeVisitor): T { - return visitor.onMethodVisibility(this) - } -} - -/** - * The mutability (payable/pure/view...) of a method changed. - */ -export class MethodMutabilityChange extends MethodValueChange { - type = "MethodMutability" - accept(visitor: ChangeVisitor): T { - return visitor.onMethodMutability(this) - } -} - -/** - * The return parameters of a method changed. - */ -export class MethodReturnChange extends MethodValueChange { - type = "MethodReturn" - accept(visitor: ChangeVisitor): T { - return visitor.onMethodReturn(this) - } -} - -export class LibraryLinkingChange extends ContractChange { - type = 'LibraryLinkingChange' - - constructor(contract: string, private readonly dependency: string) { - super(contract) - } - - getDependency() { - return this.dependency - } - - accept(visitor: ChangeVisitor): T { - return visitor.onLibraryLinking(this) - } -} diff --git a/packages/protocol/lib/compatibility/ignored-contracts-v9.ts b/packages/protocol/lib/compatibility/ignored-contracts-v9.ts deleted file mode 100644 index 6bef5c836..000000000 --- a/packages/protocol/lib/compatibility/ignored-contracts-v9.ts +++ /dev/null @@ -1,29 +0,0 @@ -export const ignoredContractsV9 = [ - // These are Mento contracts which we are no longer maintaining - 'Exchange', - 'ExchangeEUR', - 'ExchangeBRL', - 'GrandaMento', - 'StableToken', - 'StableTokenEUR', - 'StableTokenBRL', - 'StableTokenRegistry', - 'Reserve', - 'ReserveSpenderMultiSig', - - 'SortedOracles' - // Note: Sorted Oracles is a Celo Core Contract - // but as it has also been modified and deployed but the Mento team. - // We currently need work to be able to upgrade it again: - // https://github.com/celo-org/celo-monorepo/issues/10435 -] - -export function getReleaseVersion(tag: string) { - const regexp = /core-contracts.v(?.*[0-9])/gm - const matches = regexp.exec(tag) - const version = parseInt(matches?.groups?.version ?? '0', 10) - if ((version) == 0){ - throw `Tag doesn't have the correct format ${tag}` - } - return version -} diff --git a/packages/protocol/lib/compatibility/internal.ts b/packages/protocol/lib/compatibility/internal.ts deleted file mode 100644 index d2b3cc5fc..000000000 --- a/packages/protocol/lib/compatibility/internal.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { Contract as ZContract } from '@openzeppelin/upgrades' -const Web3 = require('web3') -const web3 = new Web3(null) - -// getStorageLayout needs an oz-sdk Contract class instance. This class is a -// subclass of Contract from web3-eth-contract, with an added .schema member and -// several methods. -// -// Couldn't find an easy way of getting one just from contract artifacts. But -// for getStorageLayout we really only need .schema.ast and .schema.contractName. -export function makeZContract(artifact: any): ZContract { - const web3Contract = new web3.eth.Contract(artifact.abi) - // @ts-ignore - const contract = web3Contract as Contract - // @ts-ignore - contract.schema = {} - contract.schema.ast = artifact.ast - contract.schema.contractName = artifact.contractName - contract.schema.deployedBytecode = artifact.deployedBytecode - return contract -} - -// Inlined from OpenZeppelin SDK since its not exported. -export interface Artifact { - abi: any[] - ast: any - bytecode: string - compiler: any - contractName: string - deployedBytecode: string - deployedSourceMap: string - fileName: string - legacyAST?: any - networks: any - schemaVersion: string - source: string - sourceMap: string - sourcePath: string - updatedAt: string -} - -// Inlined from OpenZeppelin SDK since its not exported. -export interface TypeInfo { - id: string; - kind: string; - label: string; - valueType?: string; - length?: number; - members?: StorageInfo[]; - src?: any; -} - -// Inlined from OpenZeppelin SDK since its not exported. -export interface StorageInfo { - label: string; - astId: number; - type: any; - src: string; - path?: string; - contract?: string; -} - diff --git a/packages/protocol/lib/compatibility/library-linking.ts b/packages/protocol/lib/compatibility/library-linking.ts deleted file mode 100644 index e11a66bae..000000000 --- a/packages/protocol/lib/compatibility/library-linking.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { ASTCodeCompatibilityReport } from '@celo/protocol/lib/compatibility/ast-code' -import { LibraryLinkingChange } from '@celo/protocol/lib/compatibility/change' -import { ContractDependencies } from '@celo/protocol/lib/contract-dependencies' - -// For each contract whose linked library dependencies have been updated, keeps -// a list of those updated libraries. -interface LibraryLinkingReport { - [contract: string]: string[] -} - -const getChangedLinkedLibraries = (linkedLibraries: string[], codeReport: ASTCodeCompatibilityReport) => { - const changedLinkedLibraries = new Set() - - codeReport.getChanges().forEach(change => { - if (linkedLibraries.includes(change.getContract())) { - changedLinkedLibraries.add(change.getContract()) - } - }) - - return changedLinkedLibraries -} - -const reportToChanges = (report: LibraryLinkingReport): LibraryLinkingChange[] => { - return Object.keys(report).map(contract => { - return report[contract].map(library => new LibraryLinkingChange(contract, library)) - }).reduce((changes, contractChanges) => changes.concat(contractChanges), []) -} - -export const reportLibraryLinkingIncompatibilities = (linkedLibraries: { [library: string]: string[] }, codeReport: ASTCodeCompatibilityReport): LibraryLinkingChange[] => { - const dependencies = new ContractDependencies(linkedLibraries) - - const changedLinkedLibraries = getChangedLinkedLibraries(Object.keys(linkedLibraries), codeReport) - const libraryLinkingReport = {} - - // To robustly handle the possibility of multiple layers of linking, we - // iterate until `changedLinkedLibraries` stabilizes. - let previousChangedLinkedLibrariesSize = 0 - while (previousChangedLinkedLibrariesSize !== changedLinkedLibraries.size) { - previousChangedLinkedLibrariesSize = changedLinkedLibraries.size - dependencies.dependencies.forEach((libraries: string[], contract: string) => { - const relevantChangedLibraries = - libraries.filter(library => changedLinkedLibraries.has(library)) - - if (relevantChangedLibraries.length > 0) { - libraryLinkingReport[contract] = relevantChangedLibraries - - // Is this contract is a linked library itself? If so, add it to the - // set. - if (linkedLibraries[contract]) { - changedLinkedLibraries.add(contract) - } - } - }) - } - - return reportToChanges(libraryLinkingReport) -} diff --git a/packages/protocol/lib/compatibility/report.ts b/packages/protocol/lib/compatibility/report.ts deleted file mode 100644 index 615e54242..000000000 --- a/packages/protocol/lib/compatibility/report.ts +++ /dev/null @@ -1,214 +0,0 @@ -// tslint:disable: max-classes-per-file -import { BuildArtifacts } from '@openzeppelin/upgrades' -import ContractAST from '@openzeppelin/upgrades/lib/utils/ContractAST' - -import { ASTCodeCompatibilityReport } from '@celo/protocol/lib/compatibility/ast-code' -import { ASTStorageCompatibilityReport } from '@celo/protocol/lib/compatibility/ast-layout' -import { categorize, Categorizer, ChangeType } from '@celo/protocol/lib/compatibility/categorizer' -import { Change } from '@celo/protocol/lib/compatibility/change' -import { makeZContract } from '@celo/protocol/lib/compatibility/internal' -import { ContractVersionDelta, ContractVersionDeltaIndex } from '@celo/protocol/lib/compatibility/version' -/** - * Value object holding all uncategorized storage and code reports. - */ -export class ASTReports { - constructor( - public readonly code: ASTCodeCompatibilityReport, - public readonly storage: ASTStorageCompatibilityReport[], - public readonly libraryLinking: Change[] - ) {} - - /** - * @return a new {@link ASTReports} with the same storage and code - * reports, excluding all contract names that match the {@param exclude} - * parameter. - */ - excluding = (exclude: RegExp): ASTReports => { - const included = (contract: string): boolean => { - if (exclude != null) { - return !exclude.test(contract) - } - return true - } - const codeReport = new ASTCodeCompatibilityReport(this.code.getChanges().filter(r => included(r.getContract()))) - const storageReports = this.storage.filter(r => included(r.contract)) - - const libraryLinkingReport = this.libraryLinking.filter(change => included(change.getContract())) - - return new ASTReports(codeReport, storageReports, libraryLinkingReport) - } -} - -/** - * A mapping {contract name => {@link CategorizedChanges}}. - */ -export interface CategorizedChangesIndex { - [contract: string]: CategorizedChanges; -} - -/** - * A {@link CategorizedChanges} builder pattern implementation. - */ -class CategorizedChangesBuilder { - public storage: ASTStorageCompatibilityReport[] = [] - public major: Change[] = [] - public minor: Change[] = [] - public patch: Change[] = [] - build = (): CategorizedChanges => { - return new CategorizedChanges(this.storage, this.major, this.minor, this.patch) - } -} - -/** - * A semantic versioning categorization of a list of contract storage - * and code changes. - */ -export class CategorizedChanges { - - /** - * @returns a new {@link CategorizedChanges} according to - * the {@link Categorizer} given. - */ - static fromReports( - reports: ASTReports, - categorizer: Categorizer): CategorizedChanges { - const storage = reports.storage.filter(r => !r.compatible) - const storageExpandedReports = reports.storage.filter(r => r.expanded) - const c = categorize(reports.code.getChanges().concat(reports.libraryLinking), categorizer) - const major = [...c[ChangeType.Major], ...storageExpandedReports.map(r => ({ getContract: () => r.contract, accept: () => null}))] - const minor = c[ChangeType.Minor] - const patch = c[ChangeType.Patch] - return new CategorizedChanges(storage, major, minor, patch) - } - - constructor( - public readonly storage: ASTStorageCompatibilityReport[], - public readonly major: Change[], - public readonly minor: Change[], - public readonly patch: Change[]) {} - - /** - * @returns a mapping {contract name => {@link CategorizedChanges}} - */ - byContract = (): CategorizedChangesIndex => { - const builders: {[contract: string]: CategorizedChangesBuilder} = {} - const builder = (contract: string) => { - if (!builders.hasOwnProperty(contract)) { - builders[contract] = new CategorizedChangesBuilder() - } - return builders[contract] - } - this.storage.forEach((r: ASTStorageCompatibilityReport) => builder(r.contract).storage.push(r)) - this.major.forEach((c: Change) => builder(c.getContract()).major.push(c)) - this.minor.forEach((c: Change) => builder(c.getContract()).minor.push(c)) - this.patch.forEach((c: Change) => builder(c.getContract()).patch.push(c)) - const ret: CategorizedChangesIndex = {} - Object.keys(builders).forEach((contract: string) => { - ret[contract] = builders[contract].build() - }) - return ret - } -} - -/** - * A mapping {contract name => {@link ASTVersionedReport}}. - */ -export interface ContractReports { - [contract: string]: ASTVersionedReport -} - -export interface ASTVersionedReportIndex { - contracts: ContractReports - libraries: CategorizedChangesIndex -} - -export const isLibrary = (contract: string, artifactsSet: BuildArtifacts[]) => { - for (const artifacts of artifactsSet){ - - const artifact = artifacts.getArtifactByName(contract) - if (artifact === undefined){ - // EAFP - // the library may be in another package - continue - } - const zContract = makeZContract(artifact) - const ast = new ContractAST(zContract, artifacts) - const kind = ast.getContractNode().contractKind - return kind === 'library' - } -} - -/** - * Backward compatibility report for a set of changes, based on - * the abstract syntax tree analysis of both the storage layout, and code API. - * - * Holds {@link CategorizedChanges} and the calculated {@link ContractVersionDelta}. - */ -export class ASTVersionedReport { - - /** - * @returns a new {@link ASTVersionedReport} with the provided - * {@link CategorizedChanges} and a calculated version delta - * according to {@link ContractVersionDelta.fromChanges}. - */ - static create = (changes: CategorizedChanges): ASTVersionedReport => { - const versionDelta = ContractVersionDelta.fromChanges( - changes.storage.length > 0, - changes.major.length > 0, - changes.minor.length > 0, - changes.patch.length > 0 - ) - return new ASTVersionedReport(changes, versionDelta) - } - - /** - * @return a new {@link ASTVersionedReportIndex} defined by - * {contract name => {@link ASTVersionedReport}}, each built - * by the {@link CategorizedChanges} for each contract. - */ - static createByContract = (changes: CategorizedChanges, artifactsSet: BuildArtifacts[]): ASTVersionedReportIndex => { - const changesByContract = changes.byContract() - const reportIndex: ASTVersionedReportIndex = { - contracts: {}, - libraries: {} - } - Object.keys(changesByContract).forEach((contract: string) => { - if (isLibrary(contract, artifactsSet)) { - reportIndex.libraries[contract] = changesByContract[contract] - } else { - const report = ASTVersionedReport.create(changesByContract[contract]) - reportIndex.contracts[contract] = report - } - }) - return reportIndex - } - - constructor( - public readonly changes: CategorizedChanges, - public readonly versionDelta: ContractVersionDelta) {} -} - -/** - * A report holding detailed {@link ASTVersionedReport} for each contract and library. - */ -export class ASTDetailedVersionedReport { - - static create = (fullReports: ASTReports, newArtifactsSet: BuildArtifacts[], categorizer: Categorizer): ASTDetailedVersionedReport => { - const changes = CategorizedChanges.fromReports(fullReports, categorizer) - const reportIndex: ASTVersionedReportIndex = ASTVersionedReport.createByContract(changes, newArtifactsSet) - return new ASTDetailedVersionedReport(reportIndex.contracts, reportIndex.libraries) - } - - constructor( - public readonly contracts: ContractReports, - public readonly libraries: CategorizedChangesIndex - ) {} - - versionDeltas = (): ContractVersionDeltaIndex => { - const deltas = {} - Object.keys(this.contracts).map((contract: string) => { - deltas[contract] = this.contracts[contract].versionDelta - }) - return deltas - } -} diff --git a/packages/protocol/lib/compatibility/utils.ts b/packages/protocol/lib/compatibility/utils.ts deleted file mode 100644 index 5482a3117..000000000 --- a/packages/protocol/lib/compatibility/utils.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { reportASTIncompatibilities } from '@celo/protocol/lib/compatibility/ast-code' -import { reportLayoutIncompatibilities } from '@celo/protocol/lib/compatibility/ast-layout' -import { Categorizer } from '@celo/protocol/lib/compatibility/categorizer' -import { reportLibraryLinkingIncompatibilities } from '@celo/protocol/lib/compatibility/library-linking' -import { ASTDetailedVersionedReport, ASTReports } from '@celo/protocol/lib/compatibility/report' -import { linkedLibraries } from '@celo/protocol/migrationsConfig' -import { BuildArtifacts, Contracts, getBuildArtifacts } from '@openzeppelin/upgrades' -import { readJsonSync } from 'fs-extra' - - - -/** - * Backward compatibility report, based on both the abstract syntax tree analysis of - * both the storage layout, and code API. - */ -export class ASTBackwardReport { - - static create = ( - oldArtifactsFolder: string, - newArtifactsFolders: string[], - oldArtifacts: BuildArtifacts, - newArtifacts: BuildArtifacts[], - exclude: RegExp, - categorizer: Categorizer, - logFunction: (msg: string) => void): ASTBackwardReport => { - - // Run reports - logFunction("Running storage report...") - const storage = reportLayoutIncompatibilities(oldArtifacts, newArtifacts) - logFunction("Done\n") - - logFunction("Running code report...") - const code = reportASTIncompatibilities(oldArtifacts, newArtifacts) - logFunction("Done\n") - - logFunction("Running library linking...") - const libraryLinking = reportLibraryLinkingIncompatibilities(linkedLibraries, code) - logFunction("Done\n") - - const fullReports = new ASTReports(code, storage, libraryLinking).excluding(exclude) - - logFunction("Generating backward report...") - const versionedReport = ASTDetailedVersionedReport.create(fullReports, newArtifacts, categorizer) - logFunction("Done\n") - - return new ASTBackwardReport( - oldArtifactsFolder, - newArtifactsFolders, - exclude.toString(), - versionedReport) - } - - constructor( - public readonly oldArtifactsFolder: string, - public readonly newArtifactsFolder: string[], - public readonly exclude: string, - public readonly report: ASTDetailedVersionedReport - ) {} -} - -function ensureValidArtifacts(artifactsPaths: string[]): void { - artifactsPaths.forEach((path) => { - const artifact = readJsonSync(path) - if (artifact.ast === undefined) { - console.error(`ERROR: invalid artifact file found: '${path}'`) - process.exit(10001) - } - }) -} - -export function instantiateArtifacts(buildDirectory: string): BuildArtifacts { - // Check if all jsons in the buildDirectory are valid artifacts, - // otherwise getBuildArtifacts fail with the enigmatic - // "Cannot read property 'absolutePath' of undefined" - ensureValidArtifacts(Contracts.listBuildArtifacts(buildDirectory)) - try { - return getBuildArtifacts(buildDirectory) - } catch (error) { - console.error(`ERROR: could not create BuildArtifacts on directory '${buildDirectory}`) - process.exit(10002) - } -} diff --git a/packages/protocol/lib/compatibility/verify-bytecode.ts b/packages/protocol/lib/compatibility/verify-bytecode.ts deleted file mode 100644 index aaab5b4a1..000000000 --- a/packages/protocol/lib/compatibility/verify-bytecode.ts +++ /dev/null @@ -1,266 +0,0 @@ -// tslint:disable: no-console -import { ensureLeading0x } from '@celo/base/lib/address' -import { - LibraryAddresses, - LibraryPositions, - linkLibraries, - stripMetadata, - verifyAndStripLibraryPrefix, -} from '@celo/protocol/lib/bytecode' -import { verifyProxyStorageProof } from '@celo/protocol/lib/proxy-utils' -import { ProposalTx } from '@celo/protocol/scripts/truffle/make-release' -import { BuildArtifacts } from '@openzeppelin/upgrades' -import { ProxyInstance, RegistryInstance } from 'types' -import Web3 from 'web3' -import { ignoredContractsV9 } from './ignored-contracts-v9' - -let ignoredContracts = [ - // This contract is not proxied - 'TransferWhitelist', - - // These contracts are not in the Registry (before release 1) - 'ReserveSpenderMultiSig', - 'GovernanceApproverMultiSig' -] - -interface VerificationContext { - artifacts: BuildArtifacts - libraryAddresses: LibraryAddresses - registry: RegistryInstance - governanceAddress: string - proposal: ProposalTx[] - Proxy: Truffle.Contract - web3: Web3 - network: string -} -interface InitializationData { - [contractName: string]: any[] -} - -const ContractNameExtractorRegex = new RegExp(/(.*)Proxy/) - -// Checks if the given transaction is a repointing of the Proxy for the given -// contract. -const isProxyRepointTransaction = (tx: ProposalTx) => - tx.contract.endsWith('Proxy') && - (tx.function === '_setImplementation' || tx.function === '_setAndInitializeImplementation') - -export const isProxyRepointAndInitializeTransaction = (tx: ProposalTx) => - tx.contract.endsWith('Proxy') && tx.function === '_setAndInitializeImplementation' - -export const isProxyRepointAndInitForIdTransaction = (tx: ProposalTx, registryId: string) => - tx.contract === registryId && isProxyRepointAndInitializeTransaction(tx) - -const isProxyRepointForIdTransaction = (tx: ProposalTx, contract: string) => - tx.contract === `${contract}Proxy` && isProxyRepointTransaction(tx) - -const isImplementationChanged = (contract: string, proposal: ProposalTx[]): boolean => - proposal.some((tx: ProposalTx) => isProxyRepointForIdTransaction(tx, contract)) - -const getProposedImplementationAddress = (contract: string, proposal: ProposalTx[]) => - proposal.find((tx: ProposalTx) => isProxyRepointForIdTransaction(tx, contract)).args[0] - -// Checks if the given transaction is a repointing of the Registry entry for the -// given registryId. -const isRegistryRepointTransaction = (tx: ProposalTx) => - tx.contract === `Registry` && tx.function === 'setAddressFor' - -const isRegistryRepointForIdTransaction = (tx: ProposalTx, registryId: string) => - isRegistryRepointTransaction(tx) && tx.args[0] === registryId - -const isProxyChanged = (contract: string, proposal: ProposalTx[]): boolean => - proposal.some((tx) => isRegistryRepointForIdTransaction(tx, contract)) - -export const getProposedProxyAddress = (contract: string, proposal: ProposalTx[]): string => { - const relevantTx = proposal.find((tx) => isRegistryRepointForIdTransaction(tx, contract)) - return relevantTx.args[1] -} - -const getSourceBytecodeFromArtifacts = (contract: string, artifacts: BuildArtifacts): string => - stripMetadata(artifacts.getArtifactByName(contract).deployedBytecode) - -const getSourceBytecode = (contract: string, context: VerificationContext): string => - getSourceBytecodeFromArtifacts(contract, context.artifacts) - -const getOnchainBytecode = async (address: string, context: VerificationContext) => - stripMetadata(await context.web3.eth.getCode(address)) - -const isLibrary = (contract: string, context: VerificationContext) => - contract in context.libraryAddresses.addresses - -const dfsStep = async (queue: string[], visited: Set, context: VerificationContext) => { - const contract = queue.pop() - // mark current DFS node as visited - visited.add(contract) - - // check proxy deployment - if (isProxyChanged(contract, context.proposal)) { - const proxyAddress = getProposedProxyAddress(contract, context.proposal) - // ganache does not support eth_getProof - if ( - context.network !== 'development' && - !(await verifyProxyStorageProof(context.web3, proxyAddress, context.governanceAddress)) - ) { - throw new Error(`Proposed ${contract}Proxy has impure storage`) - } - - const onchainProxyBytecode = await getOnchainBytecode(proxyAddress, context) - const sourceProxyBytecode = getSourceBytecode(`${contract}Proxy`, context) - if (onchainProxyBytecode !== sourceProxyBytecode) { - throw new Error(`Proposed ${contract}Proxy does not match compiled proxy bytecode`) - } - - console.log(`Proxy deployed at ${proxyAddress} matches ${contract}Proxy (bytecode and storage)`) - } - - // check implementation deployment - const sourceBytecode = getSourceBytecode(contract, context) - const sourceLibraryPositions = new LibraryPositions(sourceBytecode) - - let implementationAddress: string - if (isImplementationChanged(contract, context.proposal)) { - implementationAddress = getProposedImplementationAddress(contract, context.proposal) - } else if (isLibrary(contract, context)) { - implementationAddress = ensureLeading0x(context.libraryAddresses.addresses[contract]) - } else { - const proxyAddress = await context.registry.getAddressForString(contract) - const proxy = await context.Proxy.at(proxyAddress) // necessary await - implementationAddress = await proxy._getImplementation() - } - - let onchainBytecode = await getOnchainBytecode(implementationAddress, context) - context.libraryAddresses.collect(onchainBytecode, sourceLibraryPositions) - - let linkedSourceBytecode = linkLibraries(sourceBytecode, context.libraryAddresses.addresses) - - // normalize library bytecodes - if (isLibrary(contract, context)) { - linkedSourceBytecode = verifyAndStripLibraryPrefix(linkedSourceBytecode) - onchainBytecode = verifyAndStripLibraryPrefix(onchainBytecode, implementationAddress) - } - - if (onchainBytecode !== linkedSourceBytecode) { - throw new Error(`${contract}'s onchain and compiled bytecodes do not match`) - } else { - console.log( - `${ - isLibrary(contract, context) ? 'Library' : 'Contract' - } deployed at ${implementationAddress} matches ${contract}` - ) - } - - // push unvisited libraries to DFS queue - queue.push( - ...Object.keys(sourceLibraryPositions.positions).filter((library) => !visited.has(library)) - ) -} - -const assertValidProposalTransactions = (proposal: ProposalTx[]) => { - const invalidTransactions = proposal.filter( - (tx) => !isProxyRepointTransaction(tx) && !isRegistryRepointTransaction(tx) - ) - if (invalidTransactions.length > 0) { - throw new Error(`Proposal contains invalid release transactions ${invalidTransactions}`) - } - - console.info('Proposal contains only valid release transactions!') -} - -const assertValidInitializationData = ( - artifacts: BuildArtifacts, - proposal: ProposalTx[], - web3: Web3, - initializationData: InitializationData -) => { - const initializingProposals = proposal.filter(isProxyRepointAndInitializeTransaction) - const contractsInitialized = new Set() - for (const proposalTx of initializingProposals) { - const contractName = ContractNameExtractorRegex.exec(proposalTx.contract)[1] - - if (!initializationData[contractName]) { - throw new Error( - `Initialization Data for ${contractName} could not be found in reference file` - ) - } - - const contract = artifacts.getArtifactByName(contractName) - const initializeAbi = contract.abi.find( - (abi: any) => abi.type === 'function' && abi.name === 'initialize' - ) - const args = initializationData[contractName] - const callData = web3.eth.abi.encodeFunctionCall(initializeAbi, args) - - if (callData.toLowerCase() !== proposalTx.args[1].toLowerCase()) { - throw new Error( - `Intialization Data for ${contractName} in proposal does not match reference file ${initializationData[contractName]}` - ) - } - - contractsInitialized.add(contractName) - } - - for (const referenceContractName of Object.keys(initializationData)) { - if (!contractsInitialized.has(referenceContractName)) { - throw new Error( - `Reference file has initialization data for ${referenceContractName}, but proposal does not specify initialization` - ) - } - } - - console.info('Initialization Data was verified!') -} - -/* - * This function will visit all contracts in `contracts` as well as any - * linked libraries and verify that the compiled and linked source code matches - * the deployed bytecode registered or proposed. - */ -export const verifyBytecodes = async ( - contracts: string[], - artifacts: BuildArtifacts, - registry: RegistryInstance, - proposal: ProposalTx[], - Proxy: Truffle.Contract, - _web3: Web3, - initializationData: InitializationData = {}, - version?: number, - network = 'development' -) => { - assertValidProposalTransactions(proposal) - assertValidInitializationData(artifacts, proposal, _web3, initializationData) - - const compiledContracts = artifacts.listArtifacts().map((a) => a.contractName) - - if (version >= 9) { - ignoredContracts = [...ignoredContracts, ...ignoredContractsV9] - } - - const queue = contracts.filter( - (contract) => !ignoredContracts.includes(contract) - ).filter( - (contract) => compiledContracts.includes(contract) - ) - - const visited: Set = new Set(queue) - - // truffle web3 version does not have getProof - const web3 = new Web3(_web3.currentProvider) - - const governanceAddress = await registry.getAddressForString('Governance') - const context: VerificationContext = { - artifacts, - libraryAddresses: new LibraryAddresses(), - registry, - governanceAddress, - proposal, - Proxy, - web3, - network, - } - - while (queue.length > 0) { - await dfsStep(queue, visited, context) - } - - return context.libraryAddresses -} diff --git a/packages/protocol/lib/compatibility/version.ts b/packages/protocol/lib/compatibility/version.ts deleted file mode 100644 index 9dece2fa0..000000000 --- a/packages/protocol/lib/compatibility/version.ts +++ /dev/null @@ -1,177 +0,0 @@ -// tslint:disable: max-classes-per-file -export const DEFAULT_VERSION_STRING = '1.1.0.0' - -export class ContractVersion { - - static isValid = (version: string): boolean => { - const v = version.split(".") - if (v.length !== 4) { - return false - } - - const isNonNegativeNumber = (versionComponent): boolean => { - const number = Number(versionComponent) - return !isNaN(number) && number >= 0 - } - return v.every(isNonNegativeNumber) - } - - static fromString = (version: string): ContractVersion => { - if (!ContractVersion.isValid(version)) { - throw new Error(`Invalid version format: ${version}`) - } - const v = version.split(".") - return new ContractVersion( - Number(v[0]), - Number(v[1]), - Number(v[2]), - Number(v[3]) - ) - } - - /** - * @param version A 128 byte buffer containing the 32 byte storage, major, minor, and patch - * version numbers. - */ - static fromGetVersionNumberReturnValue = (version: Buffer): ContractVersion => { - if (version.length !== 4 * 32) { - throw new Error(`Invalid version buffer: ${version.toString('hex')}`) - } - const versions = [ - version.toString('hex', 0, 32), // Storage - version.toString('hex', 32, 64), // Major - version.toString('hex', 64, 96), // Minor - version.toString('hex', 96, 128) // Patch - ] - return ContractVersion.fromString(versions.map((x) => parseInt(x, 16)).join('.')) - } - - constructor( - public readonly storage: number, - public readonly major: number, - public readonly minor: number, - public readonly patch: number) {} - - public toString = () : string => { - const deltas = [this.storage, this.major, this.minor, this.patch] - return deltas.join('.') - } -} - -export enum Delta { - None = "=", - Increment = "+1", - Reset = "0" -} - -export class DeltaUtil { - - static applyToNumber = (delta: Delta, n: number): number => { - if (delta === Delta.None) { - return n - } - if (delta === Delta.Reset) { - return 0 - } - if (delta === Delta.Increment) { - return n + 1 - } - throw new Error(`Unexpected Delta instance: ${delta}`) - } -} - -export class ContractVersionDelta { - - static fromChanges = ( - storageChanged: boolean, - majorChanged: boolean, - minorChanged: boolean, - patchChanged: boolean): ContractVersionDelta => { - const r = Delta.Reset - const n = Delta.None - if (storageChanged) { - return new ContractVersionDelta(Delta.Increment, r, r, r) - } - if (majorChanged) { - return new ContractVersionDelta(n, Delta.Increment, r, r) - } - if (minorChanged) { - return new ContractVersionDelta(n, n, Delta.Increment, r) - } - if (patchChanged) { - return new ContractVersionDelta(n, n, n, Delta.Increment) - } - return new ContractVersionDelta(n, n, n, n) - } - - constructor( - public readonly storage: Delta, - public readonly major: Delta, - public readonly minor: Delta, - public readonly patch: Delta) {} - - appliedTo = (version: ContractVersion): ContractVersion => { - return new ContractVersion( - DeltaUtil.applyToNumber(this.storage, version.storage), - DeltaUtil.applyToNumber(this.major, version.major), - DeltaUtil.applyToNumber(this.minor, version.minor), - DeltaUtil.applyToNumber(this.patch, version.patch) - ) - } - - public toString = () : string => { - const deltas = [this.storage, this.major, this.minor, this.patch] - return deltas.map(d => d.toString()).join('.') - } - - public isVersionIncremented = () : boolean => { - return ( - this.storage === Delta.Increment || - this.major === Delta.Increment || - this.minor === Delta.Increment|| - this.patch === Delta.Increment - ) - } -} - -/** - * A mapping {contract name => {@link ContractVersionDelta}}. - */ -export interface ContractVersionDeltaIndex { - [contract: string]: ContractVersionDelta -} - -/** - * A mapping {contract name => {@link ContractVersion}}. - */ -export interface ContractVersionIndex { - [contract: string]: ContractVersion; -} - -/** - * A version checker for a specific contract. - */ -export class ContractVersionChecker { - constructor(public readonly oldVersion: ContractVersion, public readonly newVersion: ContractVersion, public readonly expectedDelta: ContractVersionDelta) {} - - public expectedVersion = (): ContractVersion => { - if (this.oldVersion === null) { - // Newly added contracts should have version 1.1.0.0 - return ContractVersion.fromString(DEFAULT_VERSION_STRING) - } else { - return this.expectedDelta.appliedTo(this.oldVersion) - } - } - - public matches = (): boolean => { - return this.newVersion.toString() === this.expectedVersion().toString() - } -} - -/** - * A mapping {contract name => {@link ContractVersionChecker}}. - */ -export interface ContractVersionCheckerIndex { - [contract: string]: ContractVersionChecker -} - diff --git a/packages/protocol/lib/contract-dependencies.ts b/packages/protocol/lib/contract-dependencies.ts deleted file mode 100644 index 0897fc3c1..000000000 --- a/packages/protocol/lib/contract-dependencies.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { linkedLibraries } from '@celo/protocol/migrationsConfig' - -export class ContractDependencies { - dependencies: Map - constructor(libraries: { [library: string]: string[] }) { - this.dependencies = new Map() - Object.keys(libraries).forEach((lib: string) => { - libraries[lib].forEach((contract: string) => { - if (this.dependencies.has(contract)) { - this.dependencies.get(contract).push(lib) - } else { - this.dependencies.set(contract, [lib]) - } - }) - }) - } - - public get = (contract: string): string[] => { - return this.dependencies.has(contract) ? this.dependencies.get(contract) : [] - } -} - -export const getCeloContractDependencies = () => { - return new ContractDependencies(linkedLibraries) -} diff --git a/packages/protocol/lib/fed-attestations-utils.ts b/packages/protocol/lib/fed-attestations-utils.ts deleted file mode 100644 index 605125afc..000000000 --- a/packages/protocol/lib/fed-attestations-utils.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { Address } from '@celo/utils/lib/address'; -import { generateTypedDataHash, structHash } from '@celo/utils/lib/sign-typed-data-utils'; -import { parseSignatureWithoutPrefix } from '@celo/utils/lib/signatureUtils'; -import { registerAttestation as getTypedData } from '@celo/utils/lib/typed-data-constructors'; -import { - bufferToHex -} from '@ethereumjs/util'; - -export const getSignatureForAttestation = async ( - identifier: string, - issuer: string, - account: string, - issuedOn: number, - signer: string, - chainId: number, - contractAddress: string -) => { - const typedData = getTypedData(chainId, contractAddress, { identifier,issuer,account, signer, issuedOn}) - - const signature = await new Promise((resolve, reject) => { - web3.currentProvider.send( - { - method: 'eth_signTypedData', - params: [signer, typedData], - }, - (error, resp) => { - if (error) { - reject(error) - } else { - resolve(resp.result) - } - } - ) - }) - - const messageHash = bufferToHex(generateTypedDataHash(typedData)) - const parsedSignature = parseSignatureWithoutPrefix(messageHash, signature, signer) - return parsedSignature -} - -export const getDomainDigest = (contractAddress: Address) => { - const typedData = getTypedData(1, contractAddress) - return bufferToHex(structHash('EIP712Domain', typedData.domain, typedData.types)) -} \ No newline at end of file diff --git a/packages/protocol/lib/memview.sol b/packages/protocol/lib/memview.sol deleted file mode 160000 index 79a08cb25..000000000 --- a/packages/protocol/lib/memview.sol +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 79a08cb25aac047d81c67c5422c9b55abfac8635 diff --git a/packages/protocol/lib/mento-core b/packages/protocol/lib/mento-core deleted file mode 160000 index 7c36d6031..000000000 --- a/packages/protocol/lib/mento-core +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 7c36d6031e0d1ed04582a38dd5de0c50f04d6cfc diff --git a/packages/protocol/lib/meta-tx-utils.ts b/packages/protocol/lib/meta-tx-utils.ts deleted file mode 100644 index 867e72339..000000000 --- a/packages/protocol/lib/meta-tx-utils.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { Address } from '@celo/utils/lib/address'; -import { generateTypedDataHash, structHash } from '@celo/utils/lib/sign-typed-data-utils'; -import { parseSignatureWithoutPrefix } from '@celo/utils/lib/signatureUtils'; -import { - bufferToHex -} from '@ethereumjs/util'; - -export interface MetaTransaction { - destination: Address - value: number - data: string - nonce: number -} -// The value currently returned by the chainId assembly code in ganache. -const chainId = 1 -const getTypedData = (walletAddress: Address, tx?: MetaTransaction) => { - const typedData = { - types: { - EIP712Domain: [ - { name: 'name', type: 'string' }, - { name: 'version', type: 'string' }, - { name: 'chainId', type: 'uint256' }, - { name: 'verifyingContract', type: 'address' }, - ], - ExecuteMetaTransaction: [ - { name: 'destination', type: 'address' }, - { name: 'value', type: 'uint256' }, - { name: 'data', type: 'bytes' }, - { name: 'nonce', type: 'uint256' }, - ], - }, - primaryType: 'ExecuteMetaTransaction', - domain: { - name: 'MetaTransactionWallet', - version: '1.1', - chainId, - verifyingContract: walletAddress, - }, - message: tx ? tx : {}, - } - return typedData -} - -export const getDomainDigest = (walletAddress: Address) => { - const typedData = getTypedData(walletAddress) - return bufferToHex( - structHash('EIP712Domain', typedData.domain, typedData.types) - ) -} - -export const constructMetaTransactionExecutionDigest = (walletAddress: Address, tx: MetaTransaction) => { - const typedData = getTypedData(walletAddress, tx) - return bufferToHex(generateTypedDataHash(typedData) ) -} - -export const getSignatureForMetaTransaction = async ( - signer: Address, - walletAddress: Address, - tx: MetaTransaction -) => { - const typedData = getTypedData(walletAddress, tx) - - const signature = await web3.currentProvider.request({ - method: 'eth_signTypedData',params: [signer, typedData], - }) - - const messageHash = constructMetaTransactionExecutionDigest(walletAddress, tx) - const parsedSignature = parseSignatureWithoutPrefix(messageHash, signature, signer) - return parsedSignature -} diff --git a/packages/protocol/lib/openzeppelin-contracts b/packages/protocol/lib/openzeppelin-contracts deleted file mode 160000 index 58a336821..000000000 --- a/packages/protocol/lib/openzeppelin-contracts +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 58a3368215581509d05bd3ec4d53cd381c9bb40e diff --git a/packages/protocol/lib/proxy-utils.ts b/packages/protocol/lib/proxy-utils.ts deleted file mode 100644 index a2bd04227..000000000 --- a/packages/protocol/lib/proxy-utils.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { Address, bufferToHex, hexToBuffer } from '@celo/base/lib/address' -import { SecureTrie } from 'merkle-patricia-tree' -import { encode as rlpEncode } from 'rlp' -import { ProxyInstance } from 'types' -import Web3 from 'web3' -import { retryTx } from './web3-utils' - -// from Proxy.sol - -// bytes32 private constant OWNER_POSITION = bytes32( -// uint256(keccak256("eip1967.proxy.admin")) - 1 -// ); -const OWNER_POSITION = '0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103' - -// bytes32 private constant IMPLEMENTATION_POSITION = bytes32( -// uint256(keccak256("eip1967.proxy.implementation")) - 1 -// ); -const IMPLEMENTATION_POSITION = '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' - -export async function verifyProxyStorageProof(web3: Web3, proxy: string, owner: string) { - const proof = await web3.eth.getProof( - web3.utils.toChecksumAddress(proxy), - [OWNER_POSITION, IMPLEMENTATION_POSITION], - 'latest' - ) - - const trie = new SecureTrie() - await trie.put(hexToBuffer(OWNER_POSITION), rlpEncode(owner)) - - // @ts-ignore - return proof.storageHash === bufferToHex(trie.root) -} - -export async function setAndInitializeImplementation( - web3: Web3, - proxy: ProxyInstance, - implementationAddress: string, - initializerAbi: any, - txOptions: { - from?: Address - value?: string - }, - ...args: any[] -) { - const callData = web3.eth.abi.encodeFunctionCall(initializerAbi, args) - if (txOptions.from != null) { - // The proxied contract needs to be funded prior to initialization - if (txOptions.value != null) { - // Proxy's fallback fn expects the contract's implementation to be set already - // So we set the implementation first, send the funding, and then set and initialize again. - await retryTx(proxy._setImplementation, [implementationAddress, { from: txOptions.from }]) - await retryTx(web3.eth.sendTransaction, [ - { - from: txOptions.from, - to: proxy.address, - value: txOptions.value, - }, - ]) - } - return retryTx(proxy._setAndInitializeImplementation, [ - implementationAddress, - callData as any, - { from: txOptions.from }, - ]) - } else { - return retryTx(proxy._setAndInitializeImplementation, [implementationAddress, callData as any]) - } -} diff --git a/packages/protocol/lib/recover-funds.ts b/packages/protocol/lib/recover-funds.ts deleted file mode 100644 index 5e65bb827..000000000 --- a/packages/protocol/lib/recover-funds.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { _setInitialProxyImplementation } from '@celo/protocol/lib/web3-utils' -import { Address } from '@celo/utils/lib/address' -import BigNumber from 'bignumber.js' -import { retryTx } from './web3-utils' - -/** - * - * - * @param proxyAddress the address of the proxy to recover funds from - * @param from the address to recover funds to - */ -export async function recoverFunds(proxyAddress: Address, from: Address) { - const ReleaseGoldMultiSig = artifacts.require('ReleaseGoldMultiSig') - const ReleaseGoldProxy = artifacts.require('ReleaseGoldProxy') - - const releaseGoldProxy = await ReleaseGoldProxy.at(proxyAddress) - const balance = await web3.eth.getBalance(releaseGoldProxy.address) - const recoveredAmount = new BigNumber(balance).minus(new BigNumber(0.001)).dp(0) - console.info(' Attempting to recover', recoveredAmount, 'CELO') - const recoveryMultiSig = await retryTx(ReleaseGoldMultiSig.new, [{ from }]) - console.info(' Assigning 1/1 multisig implementation to ReleaseGold Proxy') - await _setInitialProxyImplementation( - web3, - recoveryMultiSig, - releaseGoldProxy, - 'ReleaseGoldMultiSig', - { - from, - value: null, - }, - [from], - 1, - 1 - ) - - const proxiedMultisig = await ReleaseGoldMultiSig.at(proxyAddress) - console.info(' Transferring funds to', from) - await retryTx(proxiedMultisig.submitTransaction, [ - from, - recoveredAmount, - [], - { - from, - }, - ]) -} \ No newline at end of file diff --git a/packages/protocol/lib/registry-utils.ts b/packages/protocol/lib/registry-utils.ts deleted file mode 100644 index ddec08171..000000000 --- a/packages/protocol/lib/registry-utils.ts +++ /dev/null @@ -1,88 +0,0 @@ -/** - * Be careful when adding to this file or relying on this file. - * The verification tooling uses the CeloContractName enum as a - * source of truth for what contracts are considered "core" and - * need to be checked for backwards compatability and bytecode on - * an environment. - */ - -import { ContractPackage, MENTO_PACKAGE, SOLIDITY_08_PACKAGE } from "../contractPackages" - -export const celoRegistryAddress = '0x000000000000000000000000000000000000ce10' - -export enum CeloContractName { - Accounts = 'Accounts', - Attestations = 'Attestations', - BlockchainParameters = 'BlockchainParameters', - DoubleSigningSlasher = 'DoubleSigningSlasher', - DowntimeSlasher = 'DowntimeSlasher', - Election = 'Election', - EpochRewards = 'EpochRewards', - Escrow = 'Escrow', - Exchange = 'Exchange', - ExchangeEUR = 'ExchangeEUR', - ExchangeBRL = 'ExchangeBRL', - FederatedAttestations = 'FederatedAttestations', - FeeHandler = 'FeeHandler', - MentoFeeHandlerSeller = 'MentoFeeHandlerSeller', - FeeCurrencyWhitelist = 'FeeCurrencyWhitelist', - Freezer = 'Freezer', - GasPriceMinimum = 'GasPriceMinimum', - GoldToken = 'GoldToken', - Governance = 'Governance', - GovernanceSlasher = 'GovernanceSlasher', - GovernanceApproverMultiSig = 'GovernanceApproverMultiSig', - GrandaMento = 'GrandaMento', - LockedGold = 'LockedGold', - OdisPayments = 'OdisPayments', - Random = 'Random', - Reserve = 'Reserve', - ReserveSpenderMultiSig = 'ReserveSpenderMultiSig', - SortedOracles = 'SortedOracles', - StableToken = 'StableToken', - StableTokenEUR = 'StableTokenEUR', - StableTokenBRL = 'StableTokenBRL', - TransferWhitelist = 'TransferWhitelist', - UniswapFeeHandlerSeller = 'UniswapFeeHandlerSeller', - Validators = 'Validators', -} - -export const usesRegistry = [ - CeloContractName.Reserve, - CeloContractName.StableToken, -] - -export const hasEntryInRegistry: ContractPackage[]= [ - { - name: "default", - contracts:[ - CeloContractName.Accounts, - CeloContractName.Attestations, - CeloContractName.BlockchainParameters, - CeloContractName.DoubleSigningSlasher, - CeloContractName.DowntimeSlasher, - CeloContractName.Election, - CeloContractName.Escrow, - CeloContractName.FederatedAttestations, - CeloContractName.FeeCurrencyWhitelist, - CeloContractName.Freezer, - CeloContractName.GoldToken, - CeloContractName.GovernanceSlasher, - CeloContractName.OdisPayments, - CeloContractName.Random, - CeloContractName.SortedOracles, - ] - }, - SOLIDITY_08_PACKAGE - , - { - ...MENTO_PACKAGE, - // not all Mentro contracts are supposed to be in the Registry - contracts:[ - CeloContractName.Exchange, - CeloContractName.GrandaMento, - CeloContractName.Reserve, - CeloContractName.StableToken, - ], - } -] diff --git a/packages/protocol/lib/signing-utils.ts b/packages/protocol/lib/signing-utils.ts deleted file mode 100644 index 64e5b143f..000000000 --- a/packages/protocol/lib/signing-utils.ts +++ /dev/null @@ -1,64 +0,0 @@ -// Originally taken from https://github.com/ethereum/web3.js/blob/1.x/packages/web3-eth-accounts/src/index.js - -import { parseSignature } from '@celo/utils/lib/signatureUtils' -import { privateKeyToAddress } from '@celo/utils/lib/address' -import { LocalWallet } from '@celo/wallet-local' -import Web3 from 'web3' - -function isNot(value: any) { - return value === null || value === undefined -} - -export const getParsedSignatureOfAddress = async (web3: Web3, address: string, signer: string) => { - const addressHash = web3.utils.soliditySha3({ type: 'address', value: address }) - const signature = await web3.eth.sign(addressHash, signer) - return parseSignature(addressHash, signature, signer) -} - -export async function signTransaction(web3: Web3, txn: any, privateKey: string) { - - if (!txn) { - throw new Error('No transaction object given!') - } - - const signed = async (tx: any) => { - if (!tx.gas && !tx.gasLimit) { - throw new Error('"gas" is missing') - } - - if (tx.nonce < 0 || tx.gas < 0 || tx.gasPrice < 0 || tx.chainId < 0) { - throw new Error('Gas, gasPrice, nonce or chainId is lower than 0') - } - try { - const wallet = new LocalWallet() - - wallet.addAccount(privateKey) - - return wallet.signTransaction(tx) - - } catch (e) { - console.info('Error signing transaction', e) - throw e - } - } - - // Resolve immediately if nonce, chainId and price are provided - if (txn.nonce !== undefined && txn.chainId !== undefined && txn.gasPrice !== undefined) { - return signed(txn) - } - - // Otherwise, get the missing info from the Ethereum Node - const chainId = isNot(txn.chainId) ? await web3.eth.getChainId() : txn.chainId - const gasPrice = isNot(txn.gasPrice) ? await web3.eth.getGasPrice() : txn.gasPrice - const nonce = isNot(txn.nonce) - ? await web3.eth.getTransactionCount(privateKeyToAddress(privateKey)) - : txn.nonce - - if (isNot(chainId) || isNot(gasPrice) || isNot(nonce)) { - throw new Error( - 'One of the values "chainId", "gasPrice", or "nonce" couldn\'t be fetched: ' + - JSON.stringify({ chainId, gasPrice, nonce }) - ) - } - return signed({...txn, chainId, gasPrice, nonce }) -} diff --git a/packages/protocol/lib/solidity-bytes-utils b/packages/protocol/lib/solidity-bytes-utils deleted file mode 160000 index 14ca2bd38..000000000 --- a/packages/protocol/lib/solidity-bytes-utils +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 14ca2bd38f96f3b18c06c0cf13df1997a3831a78 diff --git a/packages/protocol/lib/test-utils.ts b/packages/protocol/lib/test-utils.ts deleted file mode 100644 index 2e1f5a432..000000000 --- a/packages/protocol/lib/test-utils.ts +++ /dev/null @@ -1,765 +0,0 @@ -import { ArtifactsSingleton } from '@celo/protocol/lib/artifactsSingleton'; -import { hasEntryInRegistry, usesRegistry } from '@celo/protocol/lib/registry-utils'; -import { getParsedSignatureOfAddress } from '@celo/protocol/lib/signing-utils'; -import { getDeployedProxiedContract } from '@celo/protocol/lib/web3-utils'; -import { config } from '@celo/protocol/migrationsConfig'; -import { privateKeyToAddress } from '@celo/utils/lib/address'; -import { soliditySha3 } from '@celo/utils/lib/solidity'; -import BigNumber from 'bignumber.js'; -import chai from 'chai'; -import chaiSubset from 'chai-subset'; -// tslint:disable-next-line: ordered-imports -import { spawn, SpawnOptions } from 'child_process'; -import { keccak256 } from 'ethereum-cryptography/keccak'; -import { GovernanceApproverMultiSigInstance, GovernanceInstance, LockedGoldInstance, ProxyInstance, RegistryInstance, UsingRegistryInstance } from 'types'; -import Web3 from 'web3'; -import { ContractPackage, MENTO_PACKAGE } from '../contractPackages'; - -// tslint:disable: ordered-imports -import { fromFixed } from '@celo/utils/src/fixidity'; -import { bufferToHex, toBuffer } from '@ethereumjs/util'; -import { utf8ToBytes } from 'ethereum-cryptography/utils'; -import { AccountsInstance } from 'types'; - - -import BN = require('bn.js') -import { getIdentifierHash, IdentifierPrefix } from "@celo/odis-identifiers" -export function getOdisHash( - phoneNumber: string, - pepper?: string, - prefix = IdentifierPrefix.PHONE_NUMBER, -) { - return getIdentifierHash(Web3.utils.sha3, phoneNumber, prefix, pepper); -} - -const isNumber = (x: any) => - typeof x === 'number' || (BN as any).isBN(x) || BigNumber.isBigNumber(x) - -chai.use(chaiSubset) - -// hard coded in ganache -export const EPOCH = 100 - -export function stripHexEncoding(hexString: string) { - return hexString.substring(0, 2) === '0x' ? hexString.substring(2) : hexString -} - -export function assertContainSubset(superset: any, subset: any) { - const assert2: any = chai.assert - return assert2.containSubset(superset, subset) -} - -export async function jsonRpc(web3: Web3, method: string, params: any[] = []): Promise { - return new Promise((resolve, reject) => { - if (typeof web3.currentProvider !== 'string') { - web3.currentProvider.send( - { - jsonrpc: '2.0', - method, - params, - // salt id generation, milliseconds might not be - // enough to generate unique ids - id: new Date().getTime() + Math.floor(Math.random() * (1 + 100 - 1)), - }, - // @ts-ignore - (err: any, result: any) => { - if (err) { - return reject(err) - } - return resolve(result) - } - ) - } else { - reject(new Error('Invalid Provider')) - } - }) -} - -export async function timeTravel(seconds: number, web3: Web3) { - await jsonRpc(web3, 'evm_increaseTime', [seconds]) - await jsonRpc(web3, 'evm_mine', []) -} - -export async function mineBlocks(blocks: number, web3: Web3) { - for (let i = 0; i < blocks; i++) { - await jsonRpc(web3, 'evm_mine', []) - } -} - -export async function currentEpochNumber(web3: Web3, epochSize: number = EPOCH) { - const blockNumber = await web3.eth.getBlockNumber() - - return getEpochNumberOfBlock(blockNumber, epochSize) -} - -export function getEpochNumberOfBlock(blockNumber: number, epochSize: number = EPOCH) { - // Follows GetEpochNumber from celo-blockchain/blob/master/consensus/istanbul/utils.go - const epochNumber = Math.floor(blockNumber / epochSize) - if (blockNumber % epochSize === 0) { - return epochNumber - } else { - return epochNumber + 1 - } -} - -// Follows GetEpochFirstBlockNumber from celo-blockchain/blob/master/consensus/istanbul/utils.go -export function getFirstBlockNumberForEpoch(epochNumber: number, epochSize: number = EPOCH) { - if (epochNumber === 0) { - // No first block for epoch 0 - return 0 - } - return (epochNumber - 1) * epochSize + 1 -} - -export async function mineToNextEpoch(web3: Web3, epochSize: number = EPOCH) { - const blockNumber = await web3.eth.getBlockNumber() - const epochNumber = await currentEpochNumber(web3, epochSize) - const blocksUntilNextEpoch = getFirstBlockNumberForEpoch(epochNumber + 1, epochSize) - blockNumber - await mineBlocks(blocksUntilNextEpoch, web3) -} - -export async function assertBalance(address: string, balance: BigNumber) { - const block = await web3.eth.getBlock('latest') - const web3balance = new BigNumber(await web3.eth.getBalance(address)) - if (isSameAddress(block.miner, address)) { - const blockReward = web3.utils.toWei(new BN(2), 'ether') as BigNumber - expectBigNumberInRange(web3balance, balance.plus(blockReward)) - } else { - expectBigNumberInRange(web3balance, balance) - } -} - -export const assertThrowsAsync = async (promise: any, errorMessage: string = '') => { - let failed = false - try { - await promise - } catch (_) { - failed = true - } - - assert.strictEqual(true, failed, errorMessage) -} - -export async function assertTransactionRevertWithReason(promise: any, expectedRevertReason: string = '') { - try { - await promise - assert.fail('Expected transaction to revert') - } catch (error) { - // Only ever tested with ganache. - // When it's a transaction (eg a non-view send call), error.message has a shape like: - // 'StatusError: Transaction: ${transactionHash} exited with an error (status 0). Reason given: ${revertMessage}.' - // Therefore we try to search for `${expectedRevertReason}`. - const revertFound: boolean = - error.message.search(expectedRevertReason) >= 0 - const msg: string = - expectedRevertReason === '' ? `Expected "StatusError", got ${error} instead` : `Expected ${expectedRevertReason}, got ${error} instead` - assert(revertFound, msg) - } -} - -export async function assertTransactionRevertWithoutReason(promise: any, errorMessage: string = '') { - // When a transaction reverts without a reason, error.message has a shape like: - // 'Transaction: ${transactionHash} exited with an error (status 0).' - try { - await promise - assert.fail('Expected transaction to revert') - } catch (error) { - const revertFound: boolean = - error.message.search('exited with an error [(]status 0[)]') >= 0 - const msg: string = - errorMessage === '' ? `Expected "StatusError", got ${error} instead` : errorMessage - assert(revertFound, msg) - } -} - -// TODO: Use assertRevert directly from openzeppelin-solidity -// Note that errorMessage is not the expected revert message, but the -// message that is provided if there is no revert. -export async function assertRevert(promise: any, errorMessage: string = '') { - // Only ever tested with ganache. - // When it's a view call, error.message has a shape like: - // `Error: VM Exception while processing transaction: revert ${expectedRevertReason}` - try { - await promise - assert.fail('Expected transaction to revert') - } catch (error) { - const revertFound: boolean = - error.message.search('VM Exception while processing transaction: revert') >= 0 - const msg: string = - errorMessage === '' ? `Expected "revert", got ${error} instead` : errorMessage - assert(revertFound, msg) - } -} - -export async function exec(command: string, args: string[]) { - console.log(`Running: ${command} ${args}`) - return new Promise((resolve, reject) => { - const proc = spawn(command, args, { - stdio: [process.stdout, process.stderr], - }) - const dataGlobal = []; - - proc.on('error', (error: any) => { - reject(error) - }) - - proc.stderr.on('data', (data: any) => { - dataGlobal.push(data.toString()) - }) - - proc.on('exit', (code: any) => { - if (code !== 0) { - reject({code, stout: dataGlobal.join(" ")}) - } else { - resolve() - } - }) - }) -} - -function execCmd(cmd: string, args: string[], options?: SpawnOptions & { silent?: boolean }) { - return new Promise(async (resolve, reject) => { - const { silent, ...spawnOptions } = options || { silent: false } - if (!silent) { - console.debug('$ ' + [cmd].concat(args).join(' ')) - } - const process = spawn(cmd, args, { ...spawnOptions, stdio: silent ? 'ignore' : 'inherit' }) - process.on('close', (code) => { - try { - resolve(code) - } catch (error) { - reject(error) - } - }) - }) -} - -async function isPortOpen(host: string, port: number) { - return (await execCmd('nc', ['-z', host, port.toString()], { silent: true })) === 0 -} - -export async function waitForPortOpen(host: string, port: number, seconds: number) { - console.info(`Waiting for ${host}:${port} to open for ${seconds}s`); - const deadline = Date.now() + seconds * 1000 - do { - if (await isPortOpen(host, port)) { - await delay(60000) // extra 60s just to give ganache extra time to startup - console.info(`Port ${host}:${port} opened`) - return true - } - } while (Date.now() < deadline) - console.info("Port was not opened in time"); - return false -} - -function delay(time) { - return new Promise((resolve) => setTimeout(resolve, time)) -} - -type ProxiedContractGetter = ( - contractName: string, - type: string, - contractPackage: ContractPackage, - ) => Promise - -type ContractGetter = ( - contractName: string, - contractPackage?: ContractPackage, - ) => Promise - - -export const assertProxiesSet = async (getContract: ProxiedContractGetter) => { - for (const contractList of proxiedContracts) { - for (const contractName of contractList.contracts) { - const contract = await getContract(contractName, 'contract', contractList.__contractPackage) - const proxy: ProxyInstance = await getContract(contractName, 'proxy', contractList.__contractPackage) - assert.strictEqual( - contract.address.toLowerCase(), - (await proxy._getImplementation()).toLowerCase(), - contractName + 'Proxy not pointing to the ' + contractName + ' implementation' - ) - } - } -} - -export const assertContractsRegistered = async (getContract: any) => { - const registry: RegistryInstance = await getContract('Registry') - for (const proxyPackage of hasEntryInRegistry) { - for (const contractName of proxyPackage.contracts) { - const contract: Truffle.ContractInstance = await getContract(contractName, proxyPackage) - assert.strictEqual( - contract.address.toLowerCase(), - (await registry.getAddressFor(soliditySha3(contractName))).toLowerCase(), - 'Registry does not have the correct information for ' + contractName - ) - } - } -} - -export const assertRegistryAddressesSet = async (getContract: ContractGetter) => { - const registry: RegistryInstance = await getContract('Registry') - for (const contractName of usesRegistry) { - const contract: UsingRegistryInstance = await getContract(contractName, MENTO_PACKAGE) - assert.strictEqual( - registry.address.toLowerCase(), - (await contract.registry()).toLowerCase(), - 'Registry address is not set properly in ' + contractName - ) - } -} - -// This function is currently not in use, it should be converted to assertContractsOwnedByGovernance -export const assertContractsOwnedByMultiSig = async (getContract: any) => { - const multiSigAddress = (await getContract('MultiSig', 'proxiedContract')).address - for (const contractList of ownedContracts) { - for (const contractName of contractList.contracts) { - const contractOwner: string = await (await getContract(contractName, 'proxiedContract', contractList.__contractPackage)).owner() - assert.strictEqual(contractOwner, multiSigAddress, contractName + ' is not owned by the MultiSig') - } - } - - for (const contractList of proxiedContracts) { - for (const contractName of contractList.contracts) { - const proxyOwner = await (await getContract(contractName, 'proxy', contractList.__contractPackage))._getOwner() - assert.strictEqual(proxyOwner, multiSigAddress, contractName + 'Proxy is not owned by the MultiSig') - }} -} - -export const assertFloatEquality = ( - a: BigNumber, - b: BigNumber, - errorMessage: string, - epsilon = new BigNumber(0.00000001) -) => { - assert(a.minus(b).abs().comparedTo(epsilon) === -1, errorMessage) -} - -export function assertLogMatches2( - log: Truffle.TransactionLog, - expected: { event: string; args: Record } -) { - assertLogMatches(log, expected.event, expected.args) -} - -export function assertLogMatches( - log: Truffle.TransactionLog, - event: string, - args: Record -) { - assert.strictEqual(log.event, event, `Log event name doesn\'t match`) - assertObjectWithBNEqual(log.args, args, (arg) => `Event ${event}, arg: ${arg} do not match`) -} - -// Compares objects' properties, using assertBNEqual to compare BN fields. -// Extracted out of previous `assertLogMatches`. -export function assertObjectWithBNEqual( - actual: object, - expected: Record, - fieldErrorMsg: (field?: string) => string -) { - const objectFields = Object.keys(actual) - .filter((k) => k !== '__length__' && isNaN(parseInt(k, 10))) - .sort() - - assert.deepStrictEqual(objectFields, Object.keys(expected).sort(), `Argument names do not match`) - for (const k of objectFields) { - if (typeof expected[k] === 'function') { - expected[k](actual[k], fieldErrorMsg(k)) - } else if (isNumber(actual[k]) || isNumber(expected[k])) { - assertEqualBN(actual[k], expected[k], fieldErrorMsg(k)) - } else if (Array.isArray(actual[k])) { - const actualArray = actual[k] as [] - const expectedArray = expected[k] as [] - if (actualArray.length === expectedArray.length - && actualArray.every(actualValue => isNumber(actualValue)) - && expectedArray.every(expectedValue => isNumber(expectedValue))) { - // if this is array of BNs, deepEqual will not work - // since it is not able to compare number/string/BN - // with each other and we have to compare it manually - for (let i = 0; i < actualArray.length; i++) { - assertEqualBN(actualArray[i], expectedArray[i], fieldErrorMsg(k)) - } - } else { - assert.deepStrictEqual(actual[k], expected[k], fieldErrorMsg(k)) - } - } - else { - assert.strictEqual(actual[k], expected[k], fieldErrorMsg(k)) - } - } -} - -export function assertBNArrayEqual( - actualArray: any[], - expectedArray: any[] -) { - assert(Array.isArray(actualArray), `Actual is not an array`) - assert(Array.isArray(expectedArray), `Expected is not an array`) - assert(actualArray.length === expectedArray.length, `Different array sizes; actual: ${actualArray.length} expected: ${expectedArray.length}`) - assert(actualArray.every(actualValue => isNumber(actualValue)) - && expectedArray.every(expectedValue => isNumber(expectedValue)), - `Expected all elements to be numbers`) - - for (let i = 0; i < actualArray.length; i++) { - assertEqualBN(actualArray[i], expectedArray[i]) - } -} - - -export function assertEqualBN( - actual: number | BN | BigNumber, - expected: number | BN | BigNumber, - msg?: string -) { - assert( - web3.utils.toBN(actual).eq(web3.utils.toBN(expected)), - `expected ${expected.toString(10)} and got ${actual.toString(10)}. ${msg || ''}` - ) -} - -export function assertAlmostEqualBN( - actual: number | BN | BigNumber, - expected: number | BN | BigNumber, - margin: number | BN | BigNumber, - msg?: string -) { - const diff = web3.utils.toBN(actual).sub(web3.utils.toBN(expected)).abs() - assert( - web3.utils.toBN(margin).gte(diff), - `expected ${expected.toString(10)} to be within ${margin.toString(10)} of ${actual.toString( - 10 - )}. ${msg || ''}` - ) -} - -export function assertEqualDpBN( - value: number | BN | BigNumber, - expected: number | BN | BigNumber, - decimals: number, - msg?: string -) { - const valueDp = new BigNumber(value.toString()).dp(decimals) - const expectedDp = new BigNumber(expected.toString()).dp(decimals) - assert( - valueDp.isEqualTo(expectedDp), - `expected ${expectedDp.toString()} and got ${valueDp.toString()}. ${msg || ''}` - ) -} - -export function assertEqualBNArray( - value: number[] | BN[] | BigNumber[], - expected: number[] | BN[] | BigNumber[], - msg?: string -) { - assert.strictEqual(value.length, expected.length, msg) - value.forEach((x, i) => assertEqualBN(x, expected[i])) -} - -export function assertGtBN( - value: number | BN | BigNumber, - expected: number | BN | BigNumber, - msg?: string -) { - assert( - web3.utils.toBN(value).gt(web3.utils.toBN(expected)), - `expected ${value.toString()} to be greater than to ${expected.toString()}. ${msg || - ''}` - ) -} - -export function assertGteBN( - value: number | BN | BigNumber, - expected: number | BN | BigNumber, - msg?: string -) { - assert( - web3.utils.toBN(value).gte(web3.utils.toBN(expected)), - `expected ${value.toString()} to be greater than or equal to ${expected.toString()}. ${ - msg || '' - }` - ) -} - -export const isSameAddress = (minerAddress, otherAddress) => { - return minerAddress.toLowerCase() === otherAddress.toLowerCase() -} - -// TODO(amy): Pull this list from the build artifacts instead -const proxiedContracts = [{ - contracts: [ - 'Attestations', - 'Escrow', - 'GoldToken', - 'Registry', - 'SortedOracles', - - ] - }, - { - contracts: [ - 'Reserve', - 'StableToken', - ], - __contractPackage: MENTO_PACKAGE - } -] - -// TODO(asa): Pull this list from the build artifacts instead -const ownedContracts = [{ - contracts: [ - 'Attestations', - 'Escrow', - 'Registry', - 'SortedOracles', - ] - },{ - contracts: [ - 'Reserve', - 'Exchange', - 'StableToken' - ], - __contractPackage: MENTO_PACKAGE - } -] - -export function getOffsetForMinerSelection( - blockhash: string, - index: number, - verifierBlockWindowSize: number -): number { - const selectedVerifierBlockOffsets = new Set() - - let hash: any = new BN(blockhash.replace('0x', ''), 16) - let verifierBlockOffset = 0 - let currentVerification = 0 - const mod = new BN(verifierBlockWindowSize) - while (currentVerification <= index) { - hash = keccak256(hash) - verifierBlockOffset = new BN(hash).mod(mod).toNumber() - if (!selectedVerifierBlockOffsets.has(verifierBlockOffset)) { - selectedVerifierBlockOffsets.add(verifierBlockOffset) - currentVerification++ - } - } - - return verifierBlockOffset -} - -export const assertSameAddress = (value: string, expected: string, msg?: string) => { - assert.strictEqual(expected.toLowerCase(), value.toLowerCase(), msg) -} - -export function createMatcher(assertFn: (value: A, expected: A, msg?: string) => void) { - return (expected: A) => (value: A, msg?: string) => { - assertFn(value, expected, msg) - } -} - -export const matchAddress = createMatcher(assertSameAddress) - -export const matchAny = () => { - // nothing -} - -export default { - assertContainSubset, - assertRevert, - timeTravel, - isSameAddress, -} - -export async function addressMinedLatestBlock(address: string) { - const block = await web3.eth.getBlock('latest') - return isSameAddress(block.miner, address) -} - -enum VoteValue { - None = 0, - Abstain, - No, - Yes, -} - -export async function assumeOwnershipWithTruffle(contractsToOwn: string[], to: string, dequeuedIndex: number = 0, contractPackage?:ContractPackage) { - const governance: GovernanceInstance = await getDeployedProxiedContract('Governance', artifacts) - const lockedGold: LockedGoldInstance = await getDeployedProxiedContract('LockedGold', artifacts) - const multiSig: GovernanceApproverMultiSigInstance = await getDeployedProxiedContract( - 'GovernanceApproverMultiSig', - artifacts - ) - const registry: RegistryInstance = await getDeployedProxiedContract('Registry', artifacts) - // Enough to pass the governance proposal unilaterally (and then some). - const tenMillionCELO = '10000000000000000000000000' - // @ts-ignore - await lockedGold.lock({ value: tenMillionCELO }) - // Any contract's `transferOwnership` function will work here as the function signatures are all the same. - // @ts-ignore - const transferOwnershipData = Buffer.from(stripHexEncoding(registry.contract.methods.transferOwnership(to).encodeABI()), 'hex') - const proposalTransactions = await Promise.all( - contractsToOwn.map(async (contractName: string) => { - - const artifactsInstance = ArtifactsSingleton.getInstance(contractPackage, artifacts) - - const contractAddress = (await getDeployedProxiedContract(contractName, artifactsInstance)).address - - return { - value: 0, - destination: contractAddress, - data: transferOwnershipData, - } - }) - ) - await governance.propose( - proposalTransactions.map((tx: any) => tx.value), - proposalTransactions.map((tx: any) => tx.destination), - // @ts-ignore - Buffer.concat(proposalTransactions.map((tx: any) => tx.data)), - proposalTransactions.map((tx: any) => tx.data.length), - 'URL', - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: web3.utils.toWei(config.governance.minDeposit.toString(), 'ether') } - ) - - const proposalId = (await governance.proposalCount()).toNumber() - - await timeTravel(config.governance.dequeueFrequency, web3) - // @ts-ignore - const txData = governance.contract.methods.approve(proposalId, dequeuedIndex).encodeABI() - await multiSig.submitTransaction(governance.address, 0, txData) - await timeTravel(config.governance.approvalStageDuration, web3) - await governance.vote(proposalId, dequeuedIndex, VoteValue.Yes) - await timeTravel(config.governance.referendumStageDuration, web3) - await governance.execute(proposalId, dequeuedIndex) -} - -/* - * Helpers for verification - */ -export enum KeyOffsets { - VALIDATING_KEY_OFFSET, - ATTESTING_KEY_OFFSET, - NEW_VALIDATING_KEY_OFFSET, - VOTING_KEY_OFFSET, -} - -// Private keys of each of the 10 miners, in the same order as their addresses in 'accounts'. -export const accountPrivateKeys: string[] = [ - '0xf2f48ee19680706196e2e339e5da3491186e0c4c5030670656b0e0164837257d', - '0x5d862464fe9303452126c8bc94274b8c5f9874cbd219789b3eb2128075a76f72', - '0xdf02719c4df8b9b8ac7f551fcb5d9ef48fa27eef7a66453879f4d8fdc6e78fb1', - '0xff12e391b79415e941a94de3bf3a9aee577aed0731e297d5cfa0b8a1e02fa1d0', - '0x752dd9cf65e68cfaba7d60225cbdbc1f4729dd5e5507def72815ed0d8abc6249', - '0xefb595a0178eb79a8df953f87c5148402a224cdf725e88c0146727c6aceadccd', - '0x83c6d2cc5ddcf9711a6d59b417dc20eb48afd58d45290099e5987e3d768f328f', - '0xbb2d3f7c9583780a7d3904a2f55d792707c345f21de1bacb2d389934d82796b2', - '0xb2fd4d29c1390b71b8795ae81196bfd60293adf99f9d32a0aff06288fcdac55f', - '0x23cb7121166b9a2f93ae0b7c05bde02eae50d64449b2cbb42bc84e9d38d6cc89', -] - -export const getDerivedKey = (offset: number, address: string, accounts: string[]) => { - const pKey = accountPrivateKeys[accounts.indexOf(address)] - const aKey = Buffer.from(pKey.slice(2), 'hex') - aKey.write((aKey[0] + offset).toString(16)) - return '0x' + aKey.toString('hex') -} - -export const unlockAndAuthorizeKey = async ( - offset: number, - authorizeFn: any, - account: string, - accounts: string[] -) => { - const key = getDerivedKey(offset, account, accounts) - const addr = privateKeyToAddress(key) - // @ts-ignore - await web3.eth.personal.importRawKey(key, 'passphrase') - await web3.eth.personal.unlockAccount(addr, 'passphrase', 1000000) - - const signature = await getParsedSignatureOfAddress(web3, account, addr) - await authorizeFn(addr, signature.v, signature.r, signature.s, { - from: account, - }) - - return addr -} - -export const authorizeAndGenerateVoteSigner = async (accountsInstance: AccountsInstance, account: string, accounts: string[]) => { - const roleHash = keccak256(utf8ToBytes('celo.org/core/vote')) - const role = bufferToHex(toBuffer(roleHash)) - - const signer = await unlockAndAuthorizeKey( - KeyOffsets.VALIDATING_KEY_OFFSET, - accountsInstance.authorizeVoteSigner, - account, - accounts - ) - // fund singer - await web3.eth.sendTransaction({ - from: accounts[9], - to: signer, - value: web3.utils.toWei('1', 'ether'), - }) - - await accountsInstance.completeSignerAuthorization(account, role, { from: signer }) - - return signer; -} - -export async function createAndAssertDelegatorDelegateeSigners(accountsInstance: AccountsInstance, accounts: string[], delegator: string, delegatee?: string) { - let delegatorSigner - let delegateeSigner; - - if (delegator != null) { - delegatorSigner = await authorizeAndGenerateVoteSigner( - accountsInstance, - delegator, - accounts - ) - assert.notEqual(delegator, delegatorSigner) - assert.equal(await accountsInstance.voteSignerToAccount(delegatorSigner), delegator) - } - - if (delegatee != null) { - delegateeSigner = await authorizeAndGenerateVoteSigner( - accountsInstance, - delegatee, - accounts - ) - assert.notEqual(delegatee, delegateeSigner) - assert.equal(await accountsInstance.voteSignerToAccount(delegateeSigner), delegatee) - } - return [delegatorSigner, delegateeSigner] -} - -export async function assertDelegatorDelegateeAmounts( - delegator: string, - delegatee: string, - percent: number, - amount: number, - lockedGold: LockedGoldInstance -) { - const [fraction, currentAmount] = await lockedGold.getDelegatorDelegateeInfo( - delegator, - delegatee - ) - assertEqualBN(fromFixed(fraction).multipliedBy(100), percent) - assertEqualBN(currentAmount, amount) -} - -export function expectBigNumberInRange(real: BigNumber, - expected: BigNumber, - range: BigNumber = new BigNumber("10000000000000000") // gas - ) { - expect( - real.plus(range).gte(expected), - `Number ${real.toString()} is not in range <${expected.minus(range).toString()}, ${expected - .plus(range) - .toString()}>` - ).to.be.true; - expect( - real.minus(range).lte(expected), - `Number ${real.toString()} is not in range <${expected.minus(range).toString()}, ${expected - .plus(range) - .toString()}>` - ).to.be.true; -} diff --git a/packages/protocol/lib/web3-utils.ts b/packages/protocol/lib/web3-utils.ts deleted file mode 100644 index b72b9d5ca..000000000 --- a/packages/protocol/lib/web3-utils.ts +++ /dev/null @@ -1,483 +0,0 @@ -/* tslint:disable:no-console */ -// TODO(asa): Refactor and rename to 'deployment-utils.ts' -import { Address, CeloTxObject } from '@celo/connect' -import { setAndInitializeImplementation } from '@celo/protocol/lib/proxy-utils' -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { signTransaction } from '@celo/protocol/lib/signing-utils' -import { privateKeyToAddress } from '@celo/utils/lib/address' -import { BuildArtifacts } from '@openzeppelin/upgrades' -import { createInterfaceAdapter } from '@truffle/interface-adapter' -import { BigNumber } from 'bignumber.js' -import path from 'path' -import prompts from 'prompts' -import { GoldTokenInstance, MultiSigInstance, OwnableInstance, ProxyContract, ProxyInstance, RegistryInstance } from 'types' -import { StableTokenInstance } from 'types/mento' -import Web3 from 'web3' -import { ContractPackage } from '../contractPackages' -import { ArtifactsSingleton } from './artifactsSingleton' - - -const truffleContract = require('@truffle/contract'); - - -export async function sendTransactionWithPrivateKey( - web3: Web3, - tx: CeloTxObject | null, - privateKey: string, - txArgs: any -) { - const address = privateKeyToAddress(privateKey) - - // Encode data and estimate gas or use default values for a transfer. - let encodedTxData: string | undefined - let estimatedGas = 21000 // Gas cost of a basic transfer. - - if (tx !== null) { - encodedTxData = tx.encodeABI() - estimatedGas = await tx.estimateGas({ - ...txArgs, - from: address, - }) - } - const signedTx = await signTransaction( - web3, - { - ...txArgs, - data: encodedTxData, - from: address, - // make sure to use enough gas but dont overspend - // or we will run into "block gas limit exceeded" errors - gas: estimatedGas * 2, - }, - privateKey - ) - - const rawTransaction = signedTx.raw - return web3.eth.sendSignedTransaction(rawTransaction) -} - -export async function convertFromContractDecimals( - value: BigNumber | number, - contract: GoldTokenInstance | StableTokenInstance -) { - const decimals = (await contract.decimals()).toNumber() - const one = new BigNumber(10).pow(decimals) - return new BigNumber(value).div(one).valueOf() -} - -interface TokenInstance { - decimals: () => Promise -} - -export async function convertToContractDecimalsBN( - value: number | BigNumber, - contract: TokenInstance -) { - const decimals = (await contract.decimals()).toNumber() - const one = new BigNumber(10).pow(decimals) - return one.times(value) -} - -/** - * @deprecated We should use BigNumber whenever possible. use convertToContractDecimalsBN() - */ -export async function convertToContractDecimals( - value: number | BigNumber, - contract: TokenInstance -) { - const bnNumber = await convertToContractDecimalsBN(value, contract) - return bnNumber.toNumber() -} - -export async function getERC20TokenBalance( - account: string, - contract: GoldTokenInstance | StableTokenInstance -) { - return convertFromContractDecimals(await contract.balanceOf(account), contract) -} - -export interface IncrementBalancesObject { - address: string - value: number | BigNumber -} - -export function parseExchangeRate(exchangeRate: BigNumber[]) { - return { - makerAmount: exchangeRate[0].toNumber(), - takerAmount: exchangeRate[1].toNumber(), - } -} - -export function parseMultiSigTransaction(transaction: [string, BigNumber, string, boolean]) { - return { - destination: transaction[0], - value: transaction[1].toNumber(), - data: transaction[2], - executed: transaction[3], - } -} - -export function parseStableTokenParams(params: BigNumber[]) { - return { - rebasePeriod: params[0].toNumber(), - lastRebase: params[1].toNumber(), - stableWindow: { - min: { - makerAmount: params[2].toNumber(), - takerAmount: params[3].toNumber(), - }, - max: { - makerAmount: params[4].toNumber(), - takerAmount: params[5].toNumber(), - }, - }, - } -} - -export function randomUint256() { - const maxUint256 = new BigNumber(2).pow(256) - return BigNumber.random() - .times(maxUint256) - .integerValue() - .valueOf() -} - -export function checkFunctionArgsLength(args: any[], abi: any) { - if (args.length !== abi.inputs.length) { - throw new Error(`Incorrect number of arguments to Solidity function: ${abi.name}`) - } -} - -export async function setInitialProxyImplementation< - ContractInstance extends Truffle.ContractInstance ->(web3: Web3, artifacts: any, contractName: string, contractPackage?: ContractPackage, ...args: any[]): Promise { - - const wrappedArtifacts = ArtifactsSingleton.getInstance(contractPackage, artifacts) - const Contract = wrappedArtifacts.require(contractName) - - // getProxy function supports the case the proxy is in a different package - // which is the case for GasPriceMimimum - const ContractProxy = wrappedArtifacts.getProxy(contractName, artifacts) - - await Contract.detectNetwork() - await ContractProxy.detectNetwork() - const implementation: ContractInstance = await Contract.deployed() - const proxy: ProxyInstance = await ContractProxy.deployed() - await _setInitialProxyImplementation(web3, implementation, proxy, contractName, { from: null, value: null }, ...args) - return Contract.at(proxy.address) as ContractInstance -} - -export async function _setInitialProxyImplementation< - ContractInstance extends Truffle.ContractInstance ->( - web3: Web3, - implementation: ContractInstance, - proxy: ProxyInstance, - contractName: string, - txOptions: { - from: Address, - value: string, - }, - ...args: any[] -) { - const initializerAbi = (implementation as any).abi.find( - (abi: any) => abi.type === 'function' && abi.name === 'initialize' - ) - - let receipt: any - if (initializerAbi) { - // TODO(Martin): check types, not just argument number - checkFunctionArgsLength(args, initializerAbi) - console.log(` Setting initial ${contractName} implementation on proxy`) - receipt = await setAndInitializeImplementation(web3, proxy, implementation.address, initializerAbi, txOptions, ...args) - } else { - if (txOptions.from != null) { - receipt = await retryTx(proxy._setImplementation, [implementation.address, { from: txOptions.from }]) - if (txOptions.value != null) { - await retryTx(web3.eth.sendTransaction, [{ - from: txOptions.from, - to: proxy.address, - value: txOptions.value, - }]) - } - } else { - receipt = await retryTx(proxy._setImplementation, [implementation.address]) - } - } - return receipt.tx -} - -export async function getDeployedProxiedContract( - contractName: string, - customArtifacts: any -): Promise { - - const Contract: Truffle.Contract = customArtifacts.require(contractName) - - let Proxy:ProxyContract - // this wrap avoids a lot of rewrite - const overloadedArtifact = ArtifactsSingleton.wrap(customArtifacts) - // if global artifacts are not defined we need to handle it - const defaultArtifacts = typeof artifacts !== 'undefined' ? artifacts : undefined; - Proxy = overloadedArtifact.getProxy(contractName, defaultArtifacts) - const proxy: ProxyInstance = await Proxy.deployed() - // @ts-ignore - Contract.numberFormat = 'BigNumber' - return Contract.at(proxy.address) as ContractInstance -} - -/* - * Abstracts away the overhead of a typical Proxy+Implementation contract deployment. - * - * Arguments: - * - artifacts: the Resolver object provided by Truffle - * - name: name of the contract to deploy - * - args: array of arguments to the contract's initializer - * - then: a callback that can perform additional migration operations after deployment - * - * The callback will be called with the deployed proxied contract, a web3 - * instance (derived from the provider of the deployer given by Truffle), and the - * name of the network (as given by Truffle). - * - * Returns: - * A function with a signature as expected to be exported from a Truffle - * migration script. - */ -export function deploymentForCoreContract( - web3: Web3, - artifacts: any, - name: CeloContractName, - args: (networkName?: string) => Promise = async () => [], - then?: (contract: ContractInstance, web3: Web3, networkName: string) => void, - artifactPath?: ContractPackage -) { - return deploymentForContract(web3, artifacts, name, args, true, then, artifactPath); -} - -export function deploymentForProxiedContract( - web3: Web3, - artifacts: any, - name: CeloContractName, - args: (networkName?: string) => Promise = async () => [], - then?: (contract: ContractInstance, web3: Web3, networkName: string) => void, - artifactPath?: ContractPackage -) { - return deploymentForContract(web3, artifacts, name, args, false, then, artifactPath); - -} - - -export const makeTruffleContractForMigrationWithoutSingleton = (contractName: string, network:any, contractPath:string, web3: Web3) => { - - const artifact = require(`${path.join(__dirname, "..")}/build/contracts-${contractPath}/${contractName}.json`) - const Contract = truffleContract({ - abi: artifact.abi, - unlinked_binary: artifact.bytecode, - }) - - - Contract.setProvider(web3.currentProvider) - Contract.setNetwork(network.network_id) - - Contract.interfaceAdapter = createInterfaceAdapter({ - networkType: "ethereum", - provider: web3.currentProvider - }) - Contract.configureNetwork({networkType: "ethereum", provider: web3.currentProvider}) - - Contract.defaults({from: network.from, gas: network.gas}) - - return Contract -} - - -export const makeTruffleContractForMigration = (contractName: string, contractPath:ContractPackage, web3: Web3) => { - const network = ArtifactsSingleton.getNetwork() - const Contract = makeTruffleContractForMigrationWithoutSingleton(contractName, network, contractPath.name, web3) - ArtifactsSingleton.getInstance(contractPath).addArtifact(contractName, Contract) - return Contract -} - -export function deploymentForContract( - web3: Web3, - artifacts: any, - name: CeloContractName, - args: (networkName?: string) => Promise = async () => [], - registerAddress: boolean, - then?: (contract: ContractInstance, web3: Web3, networkName: string, proxy?: ProxyInstance) => void, - artifactPath?: ContractPackage -) { - - console.log("-> Started deployment for", name) - let Contract - let ContractProxy - if (artifactPath) { - Contract = makeTruffleContractForMigration(name, artifactPath, web3) - - // This supports the case the proxy is in a different package - if (artifactPath.proxiesPath){ - if (artifactPath.proxiesPath == "/"){ - ContractProxy = artifacts.require(name + 'Proxy') - } else { - throw "Loading proxies for custom path not supported" - } - } else { - ContractProxy = makeTruffleContractForMigration(name + 'Proxy', artifactPath, web3) - } - } else { - Contract = artifacts.require(name) - ContractProxy = artifacts.require(name + 'Proxy') - } - - const testingDeployment = false - return (deployer: any, networkName: string, _accounts: string[]) => { - console.log("\n-> Deploying", name) - - deployer.deploy(ContractProxy) - deployer.deploy(Contract, testingDeployment) - - deployer.then(async () => { - const proxy: ProxyInstance = await ContractProxy.deployed() - await proxy._transferOwnership(ContractProxy.defaults().from) - const proxiedContract: ContractInstance = await setInitialProxyImplementation< - ContractInstance - >(web3, artifacts, name, artifactPath, ...(await args(networkName))) - if (registerAddress) { - const registry = await getDeployedProxiedContract('Registry', artifacts) - await registry.setAddressFor(name, proxiedContract.address) - } - if (then) { - await then(proxiedContract, web3, networkName, ContractProxy) - } - }) - } -} - -export async function submitMultiSigTransaction( - multiSig: MultiSigInstance, - address: string, - data: string, - value: number | BigNumber = 0 -) { - const txId = await multiSig.submitTransaction.call(address, value, data) - // @ts-ignore Typechain generating wrong type for data argument - // TODO(asa): Fix this - await multiSig.submitTransaction(address, value, data) - const txExecuted = (await multiSig.transactions(txId))[3] - if (!txExecuted) { - throw Error('Unable to execute MultiSig transaction') - } - return txId -} - -export async function transferOwnershipOfProxy( - contractName: string, - owner: string, - customArtifacts: any -) { - const Proxy = ArtifactsSingleton.wrap(customArtifacts).getProxy(contractName, artifacts) - const proxy: ProxyInstance = await Proxy.deployed() - await proxy._transferOwnership(owner) -} - -export async function transferOwnershipOfProxyAndImplementation< - ContractInstance extends OwnableInstance ->(contractName: string, owner: string, artifacts: any) { - console.log(` Transferring ownership of ${contractName} and its Proxy to ${owner}`) - const contract: ContractInstance = await getDeployedProxiedContract( - contractName, - artifacts - ) - await contract.transferOwnership(owner) - await transferOwnershipOfProxy(contractName, owner, artifacts) -} - - -/* -* Builds and returns mapping of function names to selectors. -* Each function name maps to an array of selectors to account for overloading. -*/ -export function getFunctionSelectorsForContractProxy(contract: any, proxy: any, web3:any) { - const selectors: { [index: string]: string[] } = {} - proxy.abi - .concat(contract.abi) - .filter((abiEntry: any) => abiEntry.type === 'function') - .forEach((func: any) => { - if (typeof selectors[func.name] === 'undefined') { - selectors[func.name] = [] - } - if (typeof func.signature === 'undefined') { - selectors[func.name].push(web3.eth.abi.encodeFunctionSignature(func)) - } else { - selectors[func.name].push(func.signature) - } - }) - return selectors -} - - -/* -* Builds and returns mapping of function names to selectors. -* Each function name maps to an array of selectors to account for overloading. -*/ -export function getFunctionSelectorsForContract(contract: any, contractName: string, customArtifacts: Truffle.Artifacts) { - const selectors: { [index: string]: string[] } = {} - let proxy: any = customArtifacts.require(contractName + 'Proxy') - if (proxy == null) { - const defaultArtifacts = typeof artifacts !== 'undefined' ? artifacts : undefined; - proxy = defaultArtifacts != null ? defaultArtifacts.require(contractName + 'Proxy') : proxy; - } - proxy.abi - .concat(contract.abi) - .filter((abiEntry: any) => abiEntry.type === 'function') - .forEach((func: any) => { - if (typeof selectors[func.name] === 'undefined') { - selectors[func.name] = [] - } - if (typeof func.signature === 'undefined') { - selectors[func.name].push(web3.eth.abi.encodeFunctionSignature(func)) - } else { - selectors[func.name].push(func.signature) - } - }) - return selectors -} - -// TODO: change to checkInheritance and use baseContracts field instead of importDirectives -export function checkImports(baseContractName: string, derivativeContractArtifact: any, artifacts: any) { - const isImport = (astNode: any) => astNode.nodeType === 'ImportDirective' - const imports: any[] = derivativeContractArtifact.ast.nodes.filter((astNode: any) => isImport(astNode)) - while (imports.length) { // BFS - const importedContractName = (imports.pop().file as string).split('/').pop().split('.')[0] - if (importedContractName === baseContractName) { - return true - } - const importedContractArtifact = artifacts instanceof BuildArtifacts ? - artifacts.getArtifactByName(importedContractName) : - artifacts.require(importedContractName) - imports.unshift(...importedContractArtifact.ast.nodes.filter((astNode: any) => isImport(astNode))) - } - return false -} - -export async function retryTx(fn: any, args: any[]) { - while (true) { - try { - const rvalue = await fn(...args) - return rvalue - } catch (e) { - console.error(e) - // @ts-ignore - const { confirmation } = await prompts({ - type: 'confirm', - name: 'confirmation', - // @ts-ignore: typings incorrectly only accept string. - initial: true, - message: 'Error while sending tx. Try again?', - }) - if (!confirmation) { - throw e - } - } - } -} diff --git a/packages/protocol/migrationsConfig.js b/packages/protocol/migrationsConfig.js deleted file mode 100644 index 9212953b5..000000000 --- a/packages/protocol/migrationsConfig.js +++ /dev/null @@ -1,612 +0,0 @@ -const { toFixed } = require('@celo/utils/lib/fixidity') -const { CeloContractName } = require('@celo/protocol/lib/registry-utils') - -const BigNumber = require('bignumber.js') -const minimist = require('minimist') -const path = require('path') -const lodash = require('lodash') -const web3 = require('web3') - -const argv = minimist(process.argv.slice(2), { - default: { - build_directory: path.join(__dirname, 'build'), - }, - string: ['migration_override', 'build_directory', 'network'], -}) -const network = require('./truffle-config.js').networks[argv.network] - -// Almost never use exponential notation in toString -// http://mikemcl.github.io/bignumber.js/#exponential-at -BigNumber.config({ EXPONENTIAL_AT: 1e9 }) - -const SECOND = 1 -const MINUTE = 60 * SECOND -const HOUR = 60 * MINUTE -const DAY = 24 * HOUR -const WEEK = 7 * DAY -const YEAR = 365 * DAY - -const DefaultConfig = { - attestations: { - attestationExpiryBlocks: HOUR / 5, // ~1 hour, - attestationRequestFeeInDollars: 0.05, - selectIssuersWaitBlocks: 4, - maxAttestations: 100, - }, - blockchainParameters: { - gasForNonGoldCurrencies: 50000, - deploymentBlockGasLimit: 20000000, - blockGasLimit: 13000000, - uptimeLookbackWindow: 12, - }, - doubleSigningSlasher: { - reward: '1000000000000000000000', // 1000 cGLD - penalty: '9000000000000000000000', // 9000 cGLD - }, - downtimeSlasher: { - reward: '10000000000000000000', // 10 cGLD - penalty: '100000000000000000000', // 100 cGLD - slashableDowntime: 60, // Should be overridden on public testnets - }, - election: { - minElectableValidators: '1', - maxElectableValidators: '100', - maxVotesPerAccount: 10, - electabilityThreshold: 1 / 1000, - }, - epochRewards: { - targetVotingYieldParameters: { - initial: 0, // Change to (x + 1) ^ 365 = 1.06 once Mainnet activated. - max: 0.0005, // (x + 1) ^ 365 = 1.20 - adjustmentFactor: 0, // Change to 1 / 3650 once Mainnet activated. - }, - rewardsMultiplierParameters: { - max: 2, - adjustmentFactors: { - underspend: 1 / 2, - overspend: 5, - }, - }, - // Intentionally set lower than the expected value at steady state to account for the fact that - // users may take some time to start voting with their cGLD. - targetVotingGoldFraction: 1 / 2, - maxValidatorEpochPayment: '205479452054794520547', // (75,000 / 365) * 10 ^ 18 - communityRewardFraction: 1 / 4, - carbonOffsettingPartner: '0x0000000000000000000000000000000000000000', - carbonOffsettingFraction: 1 / 1000, - frozen: false, - }, - exchange: { - spread: 5 / 1000, - reserveFraction: 1 / 100, - updateFrequency: 5 * MINUTE, - minimumReports: 1, - frozen: false, - }, - feeHandler: { - beneficiaryAddress: '0x2A486910DBC72cACcbb8d0e1439C96b03B2A4699', - burnFraction: 80 / 100, - }, - gasPriceMinimum: { - minimumFloor: 100000000, - targetDensity: 1 / 2, - adjustmentSpeed: 1 / 2, - baseFeeOpCodeActivationBlock: 0, - }, - goldToken: { - frozen: false, - }, - governance: { - queueExpiry: 4 * WEEK, - // Set to allow an attentive individual complete a governance proposal in 2 hours. - dequeueFrequency: 30 * MINUTE, - approvalStageDuration: 30 * MINUTE, - referendumStageDuration: HOUR, - executionStageDuration: DAY, - participationBaseline: 1 / 200, // Very low participation requirement given its a testnet. - concurrentProposals: 3, - minDeposit: 100, // 100 cGLD - participationBaselineFloor: 1 / 100, - participationBaselineUpdateFactor: 1 / 5, - participationBaselineQuorumFactor: 1, - }, - governanceApproverMultiSig: { - signatories: [network.from], - numRequiredConfirmations: 1, - numInternalRequiredConfirmations: 1, - useMultiSig: true, - }, - grandaMento: { - approver: network.from, - maxApprovalExchangeRateChange: 0.3, // 30% - spread: 0, // 0% - vetoPeriodSeconds: 10, // Set to 10 seconds for env-tests, this should be > time needed for a governance proposal in practice - stableTokenExchangeLimits: { - StableToken: { - min: '50000000000000000000000', // 50,000 - max: '50000000000000000000000000', // 50,000,000 - }, - StableTokenEUR: { - min: '40000000000000000000000', // 40,000 - max: '40000000000000000000000000', // 40,000,000 - }, - }, - }, - lockedGold: { - unlockingPeriod: 3 * DAY, - }, - oracles: { - reportExpiry: 5 * MINUTE, - }, - random: { - randomnessBlockRetentionWindow: HOUR / 5, // 1 hour to match attestationExpiryBlocks - }, - registry: { - predeployedProxyAddress: '0x000000000000000000000000000000000000ce10', - }, - reserve: { - tobinTaxStalenessThreshold: 100 * YEAR, // Tobin tax turned off to start - tobinTax: toFixed(0).toFixed(), // Tobin tax turned off to start - tobinTaxReserveRatio: toFixed(0).toFixed(), // Tobin tax turned off to start - dailySpendingRatio: toFixed(0.05).toFixed(), // 5% - frozenAssetsStartBalance: null, - frozenAssetsDays: null, - spenders: [], - otherAddresses: [ - '0x246f4599eFD3fA67AC44335Ed5e749E518Ffd8bB', - '0x298FbD6dad2Fc2cB56d7E37d8aCad8Bf07324f67', - ], - assetAllocationSymbols: ['cGLD', 'BTC', 'ETH', 'DAI'], - assetAllocationWeights: [0.5, 0.3, 0.15, 0.05], - }, - reserveSpenderMultiSig: { - signatories: [network.from], - numRequiredConfirmations: 1, - numInternalRequiredConfirmations: 1, - }, - stableToken: { - decimals: 18, - goldPrice: 1, - tokenName: 'Celo Dollar', - tokenSymbol: 'cUSD', - inflationRate: 1, - inflationPeriod: 1.5 * YEAR, - initialBalances: { - addresses: [network.from], - values: ['5000000000000000000000000'], - }, - oracles: [network.from], - frozen: false, - }, - stableTokenEUR: { - decimals: 18, - goldPrice: 1.2, - tokenName: 'Celo Euro', - tokenSymbol: 'cEUR', - inflationRate: 1, - inflationPeriod: 1.5 * YEAR, - initialBalances: { - addresses: [network.from], - values: ['5000000000000000000000000'], - }, - oracles: [network.from], - frozen: false, - }, - stableTokenBRL: { - decimals: 18, - goldPrice: 1.2, - tokenName: 'Celo Brazilian Real', - tokenSymbol: 'cREAL', - inflationRate: 1, - inflationPeriod: 1.5 * YEAR, - initialBalances: { - addresses: [network.from], - values: ['5000000000000000000000000'], - }, - oracles: [network.from], - frozen: false, - }, - validators: { - groupLockedGoldRequirements: { - value: '10000000000000000000000', // 10k CELO per validator - duration: 180 * DAY, - }, - validatorLockedGoldRequirements: { - value: '10000000000000000000000', // 10k CELO - // MUST BE KEPT IN SYNC WITH MEMBERSHIP HISTORY LENGTH - duration: 60 * DAY, - }, - validatorScoreParameters: { - exponent: 10, - adjustmentSpeed: 0.1, - }, - // MUST BE KEPT IN SYNC WITH VALIDATOR LOCKED GOLD DURATION - membershipHistoryLength: 60, - commissionUpdateDelay: (3 * DAY) / 5, // Approximately 3 days with 5s block times - maxGroupSize: 5, - slashingPenaltyResetPeriod: 30 * DAY, - downtimeGracePeriod: 0, - - // Register cLabs groups to contain an initial set of validators to run test networks. - validatorKeys: [], - attestationKeys: [], - groupName: 'cLabs', - commission: 0.1, - votesRatioOfLastVsFirstGroup: 2.0, - }, -} - -const NetworkConfigs = { - development: { - downtimeSlasher: { - slashableDowntime: 60, // epoch length is 100 for unit tests - }, - election: { - minElectableValidators: '10', - frozen: false, - }, - stableToken: { - initialBalances: { - addresses: ['0x5409ED021D9299bf6814279A6A1411A7e866A631'], - values: ['10000000000000000000'], - }, - }, - epochRewards: { - frozen: false, - }, - exchange: { - frozen: false, - minimumReports: 1, - }, - goldToken: { - frozen: false, - }, - reserve: { - initialBalance: 100000000, - // Add an arbitrary "otherReserveAddress" so that reserve spending can be tested. - otherAddresses: ['0x7457d5E02197480Db681D3fdF256c7acA21bDc12'], - }, - }, - testing: { - downtimeSlasher: { - slashableDowntime: 6, - }, - election: { - minElectableValidators: '1', - frozen: false, - }, - epochRewards: { - frozen: false, - targetVotingYieldParameters: { - initial: 0.00016, - max: 0.0005, - adjustmentFactor: 0.1, - }, - }, - exchange: { - frozen: false, - }, - goldToken: { - frozen: false, - }, - governance: { - skipSetConstitution: true, - skipTransferOwnership: true, - }, - governanceApproverMultiSig: { - signatories: [network.from], - numRequiredConfirmations: 1, - numInternalRequiredConfirmations: 1, - }, - stableToken: { - frozen: false, - }, - reserve: { - initialBalance: 100000000, // CELO - }, - }, - baklava: { - downtimeSlasher: { - slashableDowntime: (8 * HOUR) / 5, // ~8 hours - }, - election: { - minElectableValidators: 20, - frozen: false, - }, - epochRewards: { - targetVotingYieldParameters: { - initial: 0.00016, - }, - frozen: false, - }, - exchange: { - frozen: false, - }, - goldToken: { - frozen: false, - }, - governance: { - // Set to be able to complete a proposal in about a day, but give everyone a chance to participate. - dequeueFrequency: 4 * HOUR, - approvalStageDuration: 4 * HOUR, - referendumStageDuration: DAY, - executionStageDuration: WEEK, - participationBaseline: 1 / 200, // Very low participation requirement given its a testnet. - concurrentProposals: 3, - minDeposit: 100, // 100 cGLD - participationBaselineFloor: 1 / 100, - participationBaselineUpdateFactor: 1 / 5, - participationBaselineQuorumFactor: 1, - }, - governanceApproverMultiSig: { - // 1/5 multsig - signatories: [ - '0xb04778c00A8e30F59bFc91DD74853C4f32F34E54', // Google Cloud IAM managed account - '0x32830A3f65DF98aFCFA18bAd35009Aa51163D606', // Individual signer - '0x7c593219ad21e172c1fdc6bfdc359699fa428adb', // Individual signer - '0x31af68f73fb93815b3eB9a6FA76e63113De5f733', // Individual signer - '0x47fE4b9fFDB9712fC5793B1b5E86d96a4664cf02', // Individual signer - ], - numRequiredConfirmations: 1, - numInternalRequiredConfirmations: 2, - }, - lockedGold: { - unlockingPeriod: 6 * HOUR, // 1/12 of the Mainnet period. - }, - reserve: { - initialBalance: 100000000, // CELO - frozenAssetsStartBalance: 80000000, // Matches Mainnet after CGP-6 - frozenAssetsDays: 182, // 3x Mainnet thawing rate - }, - reserveSpenderMultiSig: { - // 1/3 multsig - signatories: [ - '0x62C6a0446BbD7f6260108dD538d88E8b53128a90', // Google Cloud IAM managed account - '0x49eFFA2ceF5FccA5540f421d6b28e76184cc0fDF', // Individual signer - '0x4550F1576fAC966Ac8b9F42e1D5D66D3A14dD8D3', // Individual signer - ], - numRequiredConfirmations: 1, - numInternalRequiredConfirmations: 2, - }, - stableToken: { - // Don't set an initial gold price before oracles start to report. - goldPrice: null, - oracles: [ - '0xd71fea6b92d3f21f659152589223385a7329bb11', - '0x1e477fc9b6a49a561343cd16b2c541930f5da7d2', - '0x460b3f8d3c203363bb65b1a18d89d4ffb6b0c981', - '0x3b522230c454ca9720665d66e6335a72327291e8', - '0x0AFe167600a5542d10912f4A07DFc4EEe0769672', - '0x412ebe7859e9aa71ff5ce4038596f6878c359c96', - '0xbbfe73df8b346b3261b19ac91235888aba36d68c', - '0x02b1d1bea682fcab4448c0820f5db409cce4f702', - '0xe90f891710f625f18ecbf1e02efb4fd1ab236a10', - '0x28c52c722df87ed11c5d7665e585e84aa93d7964', - ], - frozen: false, - }, - validators: { - groupLockedGoldRequirements: { - duration: 15 * DAY, // 1/12 of the Mainnet duration. - }, - validatorLockedGoldRequirements: { - duration: 5 * DAY, // 1/12 of the Mainnet duration. - }, - membershipHistoryLength: 15, // Number of epochs in the group lockup period. - votesRatioOfLastVsFirstGroup: 1.0, - }, - }, - alfajores: { - downtimeSlasher: { - slashableDowntime: (8 * HOUR) / 5, // ~8 hours - }, - election: { - minElectableValidators: 5, - frozen: false, - }, - epochRewards: { - targetVotingYieldParameters: { - initial: 0.00016, - }, - frozen: false, - }, - exchange: { - frozen: false, - minimumReports: 1, - }, - goldToken: { - frozen: false, - }, - governance: { - // Set to allow an attentive individual complete a governance proposal in 2 hours. - dequeueFrequency: 30 * MINUTE, - approvalStageDuration: 30 * MINUTE, - referendumStageDuration: HOUR, - executionStageDuration: DAY, - participationBaseline: 1 / 200, // Very low participation requirement given its a testnet. - concurrentProposals: 3, - minDeposit: 100, // 100 cGLD - participationBaselineFloor: 1 / 100, - participationBaselineUpdateFactor: 1 / 5, - participationBaselineQuorumFactor: 1, - }, - governanceApproverMultiSig: { - signatories: [ - '0xCc50EaC48bA71343dC76852FAE1892c6Bd2971DA', // Google Cloud IAM managed account - ], - numRequiredConfirmations: 1, - numInternalRequiredConfirmations: 1, - }, - lockedGold: { - unlockingPeriod: 6 * HOUR, // 1/12 of the Mainnet period. - }, - oracles: { - // Allow old reports so Oracle does not have to run continuously. - reportExpiry: 1000 * DAY, - }, - reserve: { - initialBalance: 100000000, // CELO - frozenAssetsStartBalance: 80000000, // Matches Mainnet after CGP-6 - frozenAssetsDays: 182, // 3x Mainnet thawing rate - otherAddresses: [], - }, - reserveSpenderMultiSig: { - signatories: [ - '0x50F5017cED9d69A47C29643bde02E0EB120E039A', // Google Cloud IAM managed account - ], - numRequiredConfirmations: 1, - numInternalRequiredConfirmations: 1, - }, - stableToken: { - oracles: [ - // Oracle addresses generated from alfajores mnemonic - '0x840b32F30e1a3b2E8b9E6C0972eBa0148E22B847', - '0x3E4DBf92e5f19BE41e1Faa6368779418A610191f', - '0xdD5Cb02066fde415dda4f04EE53fBb652066afEE', - '0x473a3be7C2A42452Ed0b521614B3b76BC59D2D1D', - '0x43c25991F0f037517D174B7E0ffD8c8Ccc471c6B', - '0x2c82F367e2eD1BA018f23219b0E3FBA60a4424d8', - '0xedf87d1e6A041cA55F857a01C10fC626C194c524', - '0x510Bf5D8feBCA69fCfe73d391783be01B3324c69', - '0xD7C06AfE310baCD786BA2929088298b9e60322ec', - '0xFc0Ea86dBDFE9CB432BaFDe251Bd2dEba022AFd7', - ], - frozen: false, - }, - validators: { - groupLockedGoldRequirements: { - duration: 15 * DAY, // 1/12 of the Mainnet duration. - }, - validatorLockedGoldRequirements: { - duration: 5 * DAY, // 1/12 of the Mainnet duration. - }, - membershipHistoryLength: 15, // Number of epochs in the group lockup period. - votesRatioOfLastVsFirstGroup: 1.0, - }, - }, - rc1: { - downtimeSlasher: { - slashableDowntime: (8 * HOUR) / 5, // ~8 hours - }, - election: { - minElectableValidators: '22', - maxElectableValidators: '100', - maxVotesPerAccount: 10, - electabilityThreshold: 1 / 1000, - frozen: true, - }, - epochRewards: { - frozen: true, - }, - goldToken: { - frozen: true, - }, - governance: { - queueExpiry: 4 * WEEK, - dequeueFrequency: DAY, // Change to 1 week once Mainnet activated - concurrentProposals: 3, - approvalStageDuration: DAY, // Change to 3 days once Mainnet activated - referendumStageDuration: 2 * DAY, // Change to 1 week once Mainnet activated - executionStageDuration: 3 * DAY, - minDeposit: 100, // 100 cGLD - participationBaseline: 5 / 100, // Start with low participation requirements, let the protocol adjust - participationBaselineFloor: 5 / 100, - participationBaselineUpdateFactor: 1 / 5, - participationBaselineQuorumFactor: 1, - }, - governanceApproverMultiSig: { - // 3/9 multsig, with 5/9 to make multisig changes. - signatories: [ - '0xBE0c3B35Ec3f759D9A67c4B7c539b0D5b52A4642', - '0xD6d48412dA0804CF88258bfDf5AaFcBe5FEd7ecC', - '0xFD74A4b05F12B9aB6020CB202aDE1BBa4Bc99aba', - '0x114a0f28f20a6cF1AD428C396f78248d0E76724e', - '0xC631Eb5dE231000f96F4973ca8516d487108b2BF', - '0xc85639289d4bbb5f90e380a0f4db6b77a2f777bf', - '0x92AD020Cde6A4e566770C603ae8315a9d7252740', - '0xba4862643d476acbc13276bd73daca7b27bf567c', - '0xe5bD469Ad2d2A160604e38ad123828B7754aa23b', - ], - numRequiredConfirmations: 3, - numInternalRequiredConfirmations: 5, - useMultiSig: true, - }, - reserveSpenderMultiSig: { - // 2/2 multsig - signatories: [ - '0x21E7082D7b0Bc12BF65296CF859E09Fe529d366d', - '0xbf4D39e774F438B6f8B8d7e56f26Fd2409F6ACF2', - ], - numRequiredConfirmations: 2, - numInternalRequiredConfirmations: 2, - }, - stableToken: { - decimals: 18, - goldPrice: 1, - tokenName: 'Celo Dollar', - tokenSymbol: 'cUSD', - inflationRate: 1, - inflationPeriod: 1.5 * YEAR, - initialBalances: { - addresses: ['0xc471776eA02705004C451959129bF09423B56526'], - values: ['5000000000000000000000000'], - }, - oracles: [ - '0x0aee051be85ba9c7c1bc635fb76b52039341ab26', - '0xd3405621f6cdcd95519a79d37f91c78e7c79cefa', - '0xe037f31121f3a96c0cc49d0cf55b2f5d6deff19e', - '0x12bad172b47287a754048f0d294221a499d1690f', - '0xacad5b2913e21ccc073b80e431fec651cd8231c6', - '0xfe9925e6ae9c4cd50ae471b90766aaef37ad307e', - '0x641c6466dae2c0b1f1f4f9c547bc3f54f4744a1d', - '0x75becd8e400552bac29cbe0534d8c7d6cba49979', - '0x223ab67272891dd352194be61597042ecf9c272a', - '0xca9ae47493f763a7166ab8310686b197984964b4', - '0xB93Fe7906ea4221b3fbe23412D18Ab1B07FE2F71', - '0x8d25D74E43789079Ef3C6B965c3D22b63A1233aC', - '0xCD88Cc79342a7cFE78E91FAa173eC87704bDcA9a', - '0x5091110175318A2A8aF88309D1648c1D84d31B29', - '0xBBd6e54Af7A5722f42461C6313F37Bd50729F195', - ], - frozen: true, - }, - }, -} - -NetworkConfigs.local = NetworkConfigs.testing -NetworkConfigs.baklavastaging = NetworkConfigs.baklava -NetworkConfigs.alfajoresstaging = NetworkConfigs.alfajores -NetworkConfigs.mainnet = NetworkConfigs.rc1 - -const linkedLibraries = { - Proposals: ['Governance', 'GovernanceTest'], - AddressLinkedList: ['Validators', 'ValidatorsTest'], - AddressSortedLinkedList: ['Election', 'ElectionTest'], - IntegerSortedLinkedList: ['Governance', 'GovernanceTest', 'IntegerSortedLinkedListTest'], - AddressSortedLinkedListWithMedian: ['SortedOracles', 'AddressSortedLinkedListWithMedianTest'], - Signatures: [ - 'Accounts', - 'Attestations', - 'AttestationsTest', - 'LockedGold', - 'Escrow', - 'MetaTransactionWallet', - 'FederatedAttestations', - ], -} - -const config = lodash.cloneDeep(DefaultConfig) - -const migrationOverride = argv.migration_override ? JSON.parse(argv.migration_override) : {} - -// Use lodash merge to deeply override defaults. -if (argv.network && NetworkConfigs[argv.network]) { - lodash.merge(config, NetworkConfigs[argv.network]) -} -lodash.merge(config, migrationOverride) - -module.exports = { - build_directory: argv.build_directory, - config, - linkedLibraries, -} diff --git a/packages/protocol/migrations_ts/00_initial_migration.ts b/packages/protocol/migrations_ts/00_initial_migration.ts deleted file mode 100644 index 735072f14..000000000 --- a/packages/protocol/migrations_ts/00_initial_migration.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* tslint:disable no-console */ -import { ArtifactsSingleton } from '../lib/artifactsSingleton' -import { networks } from '../truffle-config.js' - -module.exports = async (deployer: any, network: any) => { - const Migrations = artifacts.require('./Migrations.sol') - deployer.deploy(Migrations) - - const currentNetwork = { ...networks[network], name: network } - - console.log('Current network is', JSON.stringify(currentNetwork)) - // Instad of setting this in a singleton, it could have been set in every migration - // but it would have required quite a lot of refactoring - ArtifactsSingleton.setNetwork(currentNetwork) -} diff --git a/packages/protocol/migrations_ts/01_libraries.ts b/packages/protocol/migrations_ts/01_libraries.ts deleted file mode 100644 index 3cb33f155..000000000 --- a/packages/protocol/migrations_ts/01_libraries.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { linkedLibraries } from '@celo/protocol/migrationsConfig' - -module.exports = (deployer: any) => { - Object.keys(linkedLibraries).forEach((lib: string) => { - const Library = artifacts.require(lib) - deployer.deploy(Library) - const Contracts = linkedLibraries[lib].map((contract: string) => artifacts.require(contract)) - deployer.link(Library, Contracts) - }) -} diff --git a/packages/protocol/migrations_ts/02_registry.ts b/packages/protocol/migrations_ts/02_registry.ts deleted file mode 100644 index e81da7562..000000000 --- a/packages/protocol/migrations_ts/02_registry.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { build_directory, config } from '@celo/protocol/migrationsConfig' -import { RegistryInstance } from 'types' -import { setInitialProxyImplementation } from '../lib/web3-utils' - -const Artifactor = require('@truffle/artifactor') - -const name = 'Registry' -const Contract = artifacts.require(name) -const ContractProxy = artifacts.require(name + 'Proxy') - -module.exports = (deployer: any, _networkName: string, _accounts: string[]) => { - // tslint:disable-next-line: no-console - console.info('Deploying Registry') - deployer.deploy(ContractProxy) - deployer.deploy(Contract, false) - deployer.then(async () => { - const networkId = await web3.eth.net.getId() - // Hack to create build artifact. - const artifact = ContractProxy._json - artifact.networks[networkId] = { - address: config.registry.predeployedProxyAddress, - // @ts-ignore - transactionHash: '0x', - } - const contractsDir = build_directory + '/contracts' - const artifactor = new Artifactor(contractsDir) - - await artifactor.save(artifact) - await setInitialProxyImplementation(web3, artifacts, name) - }) -} diff --git a/packages/protocol/migrations_ts/03_freezer.ts b/packages/protocol/migrations_ts/03_freezer.ts deleted file mode 100644 index e1faed794..000000000 --- a/packages/protocol/migrations_ts/03_freezer.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* tslint:disable:no-console */ -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { deploymentForCoreContract } from '@celo/protocol/lib/web3-utils' -import { FreezerInstance } from 'types' - -const initializeArgs = async (): Promise => { - return [] -} - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.Freezer, - initializeArgs -) diff --git a/packages/protocol/migrations_ts/03_whitelist.ts b/packages/protocol/migrations_ts/03_whitelist.ts deleted file mode 100644 index 135c3f676..000000000 --- a/packages/protocol/migrations_ts/03_whitelist.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { deploymentForCoreContract } from '@celo/protocol/lib/web3-utils' -import { FeeCurrencyWhitelistInstance } from 'types' - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.FeeCurrencyWhitelist -) diff --git a/packages/protocol/migrations_ts/04_goldtoken.ts b/packages/protocol/migrations_ts/04_goldtoken.ts deleted file mode 100644 index 5fd15cad7..000000000 --- a/packages/protocol/migrations_ts/04_goldtoken.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* tslint:disable:no-console */ -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { - deploymentForCoreContract, - getDeployedProxiedContract, -} from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { FreezerInstance, GoldTokenInstance } from 'types' - -const initializeArgs = async () => { - return [config.registry.predeployedProxyAddress] -} - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.GoldToken, - initializeArgs, - async (goldToken: GoldTokenInstance) => { - if (config.goldToken.frozen) { - const freezer: FreezerInstance = await getDeployedProxiedContract( - 'Freezer', - artifacts - ) - await freezer.freeze(goldToken.address) - } - } -) diff --git a/packages/protocol/migrations_ts/05_sortedoracles.ts b/packages/protocol/migrations_ts/05_sortedoracles.ts deleted file mode 100644 index c4c8da207..000000000 --- a/packages/protocol/migrations_ts/05_sortedoracles.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* tslint:disable:no-console */ -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { deploymentForCoreContract } from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { SortedOraclesInstance } from 'types' - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.SortedOracles, - async () => [config.oracles.reportExpiry] -) diff --git a/packages/protocol/migrations_ts/06_gaspriceminimum.ts b/packages/protocol/migrations_ts/06_gaspriceminimum.ts deleted file mode 100644 index 1dac16b3c..000000000 --- a/packages/protocol/migrations_ts/06_gaspriceminimum.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* tslint:disable:no-console */ -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { deploymentForCoreContract } from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { toFixed } from '@celo/utils/lib/fixidity' -import { GasPriceMinimumInstance } from 'types/08' -import { SOLIDITY_08_PACKAGE } from '../contractPackages' - -const initializeArgs = async (): Promise => { - return [ - config.registry.predeployedProxyAddress, - config.gasPriceMinimum.minimumFloor, - toFixed(config.gasPriceMinimum.targetDensity).toString(), - toFixed(config.gasPriceMinimum.adjustmentSpeed).toString(), - config.gasPriceMinimum.baseFeeOpCodeActivationBlock, - ] -} - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.GasPriceMinimum, - initializeArgs, - undefined, - SOLIDITY_08_PACKAGE -) diff --git a/packages/protocol/migrations_ts/07_reserve_spender_multisig.ts b/packages/protocol/migrations_ts/07_reserve_spender_multisig.ts deleted file mode 100644 index b51f72704..000000000 --- a/packages/protocol/migrations_ts/07_reserve_spender_multisig.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { - deploymentForProxiedContract, - transferOwnershipOfProxy, -} from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { ReserveSpenderMultiSigInstance } from 'types/mento' -import { MENTO_PACKAGE } from '../contractPackages' -import { ArtifactsSingleton } from '../lib/artifactsSingleton' - -const initializeArgs = async (): Promise => { - return [ - config.reserveSpenderMultiSig.signatories, - config.reserveSpenderMultiSig.numRequiredConfirmations, - config.reserveSpenderMultiSig.numInternalRequiredConfirmations, - ] -} - -module.exports = deploymentForProxiedContract( - web3, - artifacts, - CeloContractName.ReserveSpenderMultiSig, - initializeArgs, - async (reserveSpenderMultiSig: ReserveSpenderMultiSigInstance) => { - await transferOwnershipOfProxy( - CeloContractName.ReserveSpenderMultiSig, - reserveSpenderMultiSig.address, - ArtifactsSingleton.getInstance(MENTO_PACKAGE) - ) - }, - MENTO_PACKAGE -) diff --git a/packages/protocol/migrations_ts/08_reserve.ts b/packages/protocol/migrations_ts/08_reserve.ts deleted file mode 100644 index b269785c7..000000000 --- a/packages/protocol/migrations_ts/08_reserve.ts +++ /dev/null @@ -1,89 +0,0 @@ -/* tslint:disable:no-console */ -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { - deploymentForCoreContract, - getDeployedProxiedContract, -} from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { toFixed } from '@celo/utils/lib/fixidity' -import { RegistryInstance } from 'types' -import { ReserveInstance, ReserveSpenderMultiSigInstance } from 'types/mento' -import Web3 from 'web3' -import { MENTO_PACKAGE } from '../contractPackages' -import { ArtifactsSingleton } from '../lib/artifactsSingleton' - -import Web3Utils = require('web3-utils') - -const truffle = require('@celo/protocol/truffle-config.js') - -const initializeArgs = async (): Promise< - [string, number, string, number, number, string[], string[], string, string] -> => { - const registry: RegistryInstance = await getDeployedProxiedContract( - 'Registry', - artifacts - ) - return [ - registry.address, - config.reserve.tobinTaxStalenessThreshold, - config.reserve.dailySpendingRatio, - 0, // frozenGold cannot be set until the reserve us funded - 0, // frozenGold cannot be set until the reserve us funded - config.reserve.assetAllocationSymbols.map((assetSymbol) => - Web3Utils.padRight(Web3Utils.utf8ToHex(assetSymbol), 64) - ), - config.reserve.assetAllocationWeights.map((assetWeight) => toFixed(assetWeight).toFixed()), - config.reserve.tobinTax, - config.reserve.tobinTaxReserveRatio, - ] -} - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.Reserve, - initializeArgs, - async (reserve: ReserveInstance, web3: Web3, networkName: string) => { - config.reserve.spenders.forEach(async (spender) => { - console.info(`Marking ${spender} as a Reserve spender`) - await reserve.addSpender(spender) - }) - config.reserve.otherAddresses.forEach(async (otherAddress) => { - console.info(`Marking ${otherAddress} as an "otherReserveAddress"`) - await reserve.addOtherReserveAddress(otherAddress) - }) - - if (config.reserve.initialBalance) { - const network: any = truffle.networks[networkName] - - const block = await web3.eth.getBlock('latest') - const nextGasPrice = Math.ceil(block.baseFeePerGas) - - await web3.eth.sendTransaction({ - from: network.from, - to: reserve.address, - value: web3.utils.toWei(config.reserve.initialBalance.toString(), 'ether').toString(), - // @ts-ignore: typing not available https://github.com/web3/web3.js/issues/6123#issuecomment-1568250373 - type: 0, - gasPrice: nextGasPrice, - }) - - if (config.reserve.frozenAssetsStartBalance && config.reserve.frozenAssetsDays) { - console.info('Setting frozen asset parameters on the Reserve') - await reserve.setFrozenGold( - config.reserve.frozenAssetsStartBalance, - config.reserve.frozenAssetsDays - ) - } - } - - const reserveSpenderMultiSig: ReserveSpenderMultiSigInstance = - await getDeployedProxiedContract( - CeloContractName.ReserveSpenderMultiSig, - ArtifactsSingleton.getInstance(MENTO_PACKAGE) - ) - console.info(`Marking ${reserveSpenderMultiSig.address} as a reserve spender`) - await reserve.addSpender(reserveSpenderMultiSig.address) - }, - MENTO_PACKAGE -) diff --git a/packages/protocol/migrations_ts/09_01_stableToken_EUR.ts b/packages/protocol/migrations_ts/09_01_stableToken_EUR.ts deleted file mode 100644 index 1a864c3f3..000000000 --- a/packages/protocol/migrations_ts/09_01_stableToken_EUR.ts +++ /dev/null @@ -1,89 +0,0 @@ -/* tslint:disable:no-console */ -import { ensureLeading0x, eqAddress, NULL_ADDRESS } from '@celo/base/lib/address' -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { - deploymentForCoreContract, - getDeployedProxiedContract, -} from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { toFixed } from '@celo/utils/lib/fixidity' -import { FeeCurrencyWhitelistInstance, FreezerInstance, SortedOraclesInstance } from 'types' -import { ReserveInstance, StableTokenEURInstance } from 'types/mento' -import Web3 from 'web3' -import { MENTO_PACKAGE } from '../contractPackages' -import { ArtifactsSingleton } from '../lib/artifactsSingleton' - -const truffle = require('@celo/protocol/truffle-config.js') - -const initializeArgs = async (): Promise => { - const rate = toFixed(config.stableTokenEUR.inflationRate) - return [ - config.stableTokenEUR.tokenName, - config.stableTokenEUR.tokenSymbol, - config.stableTokenEUR.decimals, - config.registry.predeployedProxyAddress, - rate.toString(), - config.stableTokenEUR.inflationPeriod, - config.stableTokenEUR.initialBalances.addresses, - config.stableTokenEUR.initialBalances.values, - 'ExchangeEUR', - ] -} - -// TODO make this general (do it!) -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.StableTokenEUR, - initializeArgs, - async (stableToken: StableTokenEURInstance, _web3: Web3, networkName: string) => { - if (config.stableTokenEUR.frozen) { - const freezer: FreezerInstance = await getDeployedProxiedContract( - 'Freezer', - artifacts - ) - await freezer.freeze(stableToken.address) - } - const sortedOracles: SortedOraclesInstance = - await getDeployedProxiedContract('SortedOracles', artifacts) - - for (const oracle of config.stableTokenEUR.oracles) { - console.info(`Adding ${oracle} as an Oracle for StableToken (EUR)`) - await sortedOracles.addOracle(stableToken.address, ensureLeading0x(oracle)) - } - - const goldPrice = config.stableTokenEUR.goldPrice - if (goldPrice) { - const fromAddress = truffle.networks[networkName].from - const isOracle = config.stableTokenEUR.oracles.some((o) => eqAddress(o, fromAddress)) - if (!isOracle) { - console.warn( - `Gold price specified in migration but ${fromAddress} not explicitly authorized as oracle, authorizing...` - ) - await sortedOracles.addOracle(stableToken.address, ensureLeading0x(fromAddress)) - } - console.info('Reporting price of StableToken (EUR) to oracle') - await sortedOracles.report( - stableToken.address, - toFixed(goldPrice), - NULL_ADDRESS, - NULL_ADDRESS - ) - const reserve: ReserveInstance = await getDeployedProxiedContract( - 'Reserve', - ArtifactsSingleton.getInstance(MENTO_PACKAGE) - ) - console.info('Adding StableToken (EUR) to Reserve') - await reserve.addToken(stableToken.address) - } - - console.info('Whitelisting StableToken (EUR) as a fee currency') - const feeCurrencyWhitelist: FeeCurrencyWhitelistInstance = - await getDeployedProxiedContract( - 'FeeCurrencyWhitelist', - artifacts - ) - await feeCurrencyWhitelist.addToken(stableToken.address) - }, - MENTO_PACKAGE -) diff --git a/packages/protocol/migrations_ts/09_02_stableToken_BRL.ts b/packages/protocol/migrations_ts/09_02_stableToken_BRL.ts deleted file mode 100644 index 09568743d..000000000 --- a/packages/protocol/migrations_ts/09_02_stableToken_BRL.ts +++ /dev/null @@ -1,89 +0,0 @@ -/* tslint:disable:no-console */ -import { ensureLeading0x, eqAddress, NULL_ADDRESS } from '@celo/base/lib/address' -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { - deploymentForCoreContract, - getDeployedProxiedContract, -} from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { toFixed } from '@celo/utils/lib/fixidity' -import { FeeCurrencyWhitelistInstance, FreezerInstance, SortedOraclesInstance } from 'types' -import { ReserveInstance, StableTokenBRLInstance } from 'types/mento' -import Web3 from 'web3' -import { MENTO_PACKAGE } from '../contractPackages' -import { ArtifactsSingleton } from '../lib/artifactsSingleton' - -const truffle = require('@celo/protocol/truffle-config.js') - -const initializeArgs = async (): Promise => { - const rate = toFixed(config.stableTokenBRL.inflationRate) - return [ - config.stableTokenBRL.tokenName, - config.stableTokenBRL.tokenSymbol, - config.stableTokenBRL.decimals, - config.registry.predeployedProxyAddress, - rate.toString(), - config.stableTokenBRL.inflationPeriod, - config.stableTokenBRL.initialBalances.addresses, - config.stableTokenBRL.initialBalances.values, - 'ExchangeBRL', - ] -} - -// TODO make this general -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.StableTokenBRL, - initializeArgs, - async (stableToken: StableTokenBRLInstance, _web3: Web3, networkName: string) => { - if (config.stableTokenBRL.frozen) { - const freezer: FreezerInstance = await getDeployedProxiedContract( - 'Freezer', - artifacts - ) - await freezer.freeze(stableToken.address) - } - const sortedOracles: SortedOraclesInstance = - await getDeployedProxiedContract('SortedOracles', artifacts) - - for (const oracle of config.stableTokenBRL.oracles) { - console.info(`Adding ${oracle} as an Oracle for StableToken (BRL)`) - await sortedOracles.addOracle(stableToken.address, ensureLeading0x(oracle)) - } - - const goldPrice = config.stableTokenBRL.goldPrice - if (goldPrice) { - const fromAddress = truffle.networks[networkName].from - const isOracle = config.stableTokenBRL.oracles.some((o) => eqAddress(o, fromAddress)) - if (!isOracle) { - console.warn( - `Gold price specified in migration but ${fromAddress} not explicitly authorized as oracle, authorizing...` - ) - await sortedOracles.addOracle(stableToken.address, ensureLeading0x(fromAddress)) - } - console.info('Reporting price of StableToken (BRL) to oracle') - await sortedOracles.report( - stableToken.address, - toFixed(goldPrice), - NULL_ADDRESS, - NULL_ADDRESS - ) - const reserve: ReserveInstance = await getDeployedProxiedContract( - 'Reserve', - ArtifactsSingleton.getInstance(MENTO_PACKAGE) - ) - console.info('Adding StableToken (BRL) to Reserve') - await reserve.addToken(stableToken.address) - } - - console.info('Whitelisting StableToken (BRL) as a fee currency') - const feeCurrencyWhitelist: FeeCurrencyWhitelistInstance = - await getDeployedProxiedContract( - 'FeeCurrencyWhitelist', - artifacts - ) - await feeCurrencyWhitelist.addToken(stableToken.address) - }, - MENTO_PACKAGE -) diff --git a/packages/protocol/migrations_ts/09_0_stabletoken_USD.ts b/packages/protocol/migrations_ts/09_0_stabletoken_USD.ts deleted file mode 100644 index 156498f43..000000000 --- a/packages/protocol/migrations_ts/09_0_stabletoken_USD.ts +++ /dev/null @@ -1,89 +0,0 @@ -/* tslint:disable:no-console */ -import { ensureLeading0x, eqAddress, NULL_ADDRESS } from '@celo/base/lib/address' -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { - deploymentForCoreContract, - getDeployedProxiedContract, -} from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { toFixed } from '@celo/utils/lib/fixidity' -import { FeeCurrencyWhitelistInstance, FreezerInstance, SortedOraclesInstance } from 'types' -import { ReserveInstance, StableTokenInstance } from 'types/mento' -import Web3 from 'web3' -import { MENTO_PACKAGE } from '../contractPackages' -import { ArtifactsSingleton } from '../lib/artifactsSingleton' - -const truffle = require('@celo/protocol/truffle-config.js') - -const initializeArgs = async (): Promise => { - const rate = toFixed(config.stableToken.inflationRate) - return [ - config.stableToken.tokenName, - config.stableToken.tokenSymbol, - config.stableToken.decimals, - config.registry.predeployedProxyAddress, - rate.toString(), - config.stableToken.inflationPeriod, - config.stableToken.initialBalances.addresses, - config.stableToken.initialBalances.values, - 'Exchange', // USD - ] -} - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.StableToken, - initializeArgs, - async (stableToken: StableTokenInstance, _web3: Web3, networkName: string) => { - if (config.stableToken.frozen) { - const freezer: FreezerInstance = await getDeployedProxiedContract( - 'Freezer', - artifacts - ) - await freezer.freeze(stableToken.address) - } - - const sortedOracles: SortedOraclesInstance = - await getDeployedProxiedContract('SortedOracles', artifacts) - - for (const oracle of config.stableToken.oracles) { - console.info(`Adding ${oracle} as an Oracle for StableToken (USD)`) - await sortedOracles.addOracle(stableToken.address, ensureLeading0x(oracle)) - } - - const goldPrice = config.stableToken.goldPrice - if (goldPrice) { - const fromAddress = truffle.networks[networkName].from - const isOracle = config.stableToken.oracles.some((o) => eqAddress(o, fromAddress)) - if (!isOracle) { - console.warn( - `Gold price specified in migration but ${fromAddress} not explicitly authorized as oracle, authorizing...` - ) - await sortedOracles.addOracle(stableToken.address, ensureLeading0x(fromAddress)) - } - console.info('Reporting price of StableToken (USD) to oracle') - await sortedOracles.report( - stableToken.address, - toFixed(goldPrice), - NULL_ADDRESS, - NULL_ADDRESS - ) - const reserve: ReserveInstance = await getDeployedProxiedContract( - 'Reserve', - ArtifactsSingleton.getInstance(MENTO_PACKAGE) - ) - console.info('Adding StableToken (USD) to Reserve') - await reserve.addToken(stableToken.address) - } - - console.info('Whitelisting StableToken (USD) as a fee currency') - const feeCurrencyWhitelist: FeeCurrencyWhitelistInstance = - await getDeployedProxiedContract( - 'FeeCurrencyWhitelist', - artifacts - ) - await feeCurrencyWhitelist.addToken(stableToken.address) - }, - MENTO_PACKAGE -) diff --git a/packages/protocol/migrations_ts/10_01_exchange_EUR.ts b/packages/protocol/migrations_ts/10_01_exchange_EUR.ts deleted file mode 100644 index 3a158e16c..000000000 --- a/packages/protocol/migrations_ts/10_01_exchange_EUR.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* tslint:disable:no-console */ - -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { - deploymentForCoreContract, - getDeployedProxiedContract, -} from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { toFixed } from '@celo/utils/lib/fixidity' -import { FreezerInstance } from 'types' -import { ExchangeEURInstance, ReserveInstance } from 'types/mento' -import { MENTO_PACKAGE } from '../contractPackages' -import { ArtifactsSingleton } from '../lib/artifactsSingleton' - -const initializeArgs = async (): Promise => { - return [ - config.registry.predeployedProxyAddress, - CeloContractName.StableTokenEUR, - toFixed(config.exchange.spread).toString(), - toFixed(config.exchange.reserveFraction).toString(), - config.exchange.updateFrequency, - config.exchange.minimumReports, - ] -} - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.ExchangeEUR, - initializeArgs, - async (exchange: ExchangeEURInstance) => { - if (config.exchange.frozen) { - const freezer: FreezerInstance = await getDeployedProxiedContract( - 'Freezer', - artifacts - ) - await freezer.freeze(exchange.address) - } - - const reserve: ReserveInstance = await getDeployedProxiedContract( - 'Reserve', - ArtifactsSingleton.getInstance(MENTO_PACKAGE) - ) - // cUSD doesn't need to be added as it is currently harcoded in Reserve.sol - await reserve.addExchangeSpender(exchange.address) - await exchange.activateStable() - }, - MENTO_PACKAGE -) diff --git a/packages/protocol/migrations_ts/10_02_exchange_BRL.ts b/packages/protocol/migrations_ts/10_02_exchange_BRL.ts deleted file mode 100644 index a12fc3de8..000000000 --- a/packages/protocol/migrations_ts/10_02_exchange_BRL.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* tslint:disable:no-console */ - -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { - deploymentForCoreContract, - getDeployedProxiedContract, -} from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { toFixed } from '@celo/utils/lib/fixidity' -import { FreezerInstance } from 'types' -import { ExchangeBRLInstance, ReserveInstance } from 'types/mento' -import { MENTO_PACKAGE } from '../contractPackages' -import { ArtifactsSingleton } from '../lib/artifactsSingleton' - -const initializeArgs = async (): Promise => { - return [ - config.registry.predeployedProxyAddress, - CeloContractName.StableTokenBRL, - toFixed(config.exchange.spread).toString(), - toFixed(config.exchange.reserveFraction).toString(), - config.exchange.updateFrequency, - config.exchange.minimumReports, - ] -} - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.ExchangeBRL, - initializeArgs, - async (exchange: ExchangeBRLInstance) => { - if (config.exchange.frozen) { - const freezer: FreezerInstance = await getDeployedProxiedContract( - 'Freezer', - artifacts - ) - await freezer.freeze(exchange.address) - } - - const reserve: ReserveInstance = await getDeployedProxiedContract( - 'Reserve', - ArtifactsSingleton.getInstance(MENTO_PACKAGE) - ) - // cUSD doesn't need to be added as it is currently harcoded in Reserve.sol - await reserve.addExchangeSpender(exchange.address) - await exchange.activateStable() - }, - MENTO_PACKAGE -) diff --git a/packages/protocol/migrations_ts/10_0_exchange_USD.ts b/packages/protocol/migrations_ts/10_0_exchange_USD.ts deleted file mode 100644 index 9fb48f25f..000000000 --- a/packages/protocol/migrations_ts/10_0_exchange_USD.ts +++ /dev/null @@ -1,41 +0,0 @@ -/* tslint:disable:no-console */ - -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { - deploymentForCoreContract, - getDeployedProxiedContract, -} from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { toFixed } from '@celo/utils/lib/fixidity' -import { FreezerInstance } from 'types' -import { ExchangeInstance } from 'types/mento' -import { MENTO_PACKAGE } from '../contractPackages' - -const initializeArgs = async (): Promise => { - return [ - config.registry.predeployedProxyAddress, - CeloContractName.StableToken, - toFixed(config.exchange.spread).toString(), - toFixed(config.exchange.reserveFraction).toString(), - config.exchange.updateFrequency, - config.exchange.minimumReports, - ] -} - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.Exchange, - initializeArgs, - async (exchange: ExchangeInstance) => { - if (config.exchange.frozen) { - const freezer: FreezerInstance = await getDeployedProxiedContract( - 'Freezer', - artifacts - ) - await freezer.freeze(exchange.address) - } - await exchange.activateStable() - }, - MENTO_PACKAGE -) diff --git a/packages/protocol/migrations_ts/11_accounts.ts b/packages/protocol/migrations_ts/11_accounts.ts deleted file mode 100644 index d72f57ad6..000000000 --- a/packages/protocol/migrations_ts/11_accounts.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { - deploymentForCoreContract, - getDeployedProxiedContract, -} from '@celo/protocol/lib/web3-utils' -import { AccountsInstance, RegistryInstance } from 'types' - -const initializeArgs = async (): Promise<[string]> => { - const registry: RegistryInstance = await getDeployedProxiedContract( - 'Registry', - artifacts - ) - return [registry.address] -} - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.Accounts, - initializeArgs, - async (accounts: AccountsInstance) => { - await accounts.setEip712DomainSeparator() - } -) diff --git a/packages/protocol/migrations_ts/12_lockedgold.ts b/packages/protocol/migrations_ts/12_lockedgold.ts deleted file mode 100644 index 5eb603e7f..000000000 --- a/packages/protocol/migrations_ts/12_lockedgold.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { deploymentForCoreContract } from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { LockedGoldInstance } from 'types' - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.LockedGold, - async () => [config.registry.predeployedProxyAddress, config.lockedGold.unlockingPeriod] -) diff --git a/packages/protocol/migrations_ts/13_validators.ts b/packages/protocol/migrations_ts/13_validators.ts deleted file mode 100644 index 2cc51d2ae..000000000 --- a/packages/protocol/migrations_ts/13_validators.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { deploymentForCoreContract } from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { toFixed } from '@celo/utils/lib/fixidity' -import { ValidatorsInstance } from 'types' - -const initializeArgs = async (): Promise => { - return [ - config.registry.predeployedProxyAddress, - config.validators.groupLockedGoldRequirements.value, - config.validators.groupLockedGoldRequirements.duration, - config.validators.validatorLockedGoldRequirements.value, - config.validators.validatorLockedGoldRequirements.duration, - config.validators.validatorScoreParameters.exponent, - toFixed(config.validators.validatorScoreParameters.adjustmentSpeed).toFixed(), - config.validators.membershipHistoryLength, - config.validators.slashingPenaltyResetPeriod, - config.validators.maxGroupSize, - config.validators.commissionUpdateDelay, - config.validators.downtimeGracePeriod, - ] -} - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.Validators, - initializeArgs -) diff --git a/packages/protocol/migrations_ts/14_election.ts b/packages/protocol/migrations_ts/14_election.ts deleted file mode 100644 index 9f48f7a1d..000000000 --- a/packages/protocol/migrations_ts/14_election.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* tslint:disable:no-console */ -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { deploymentForCoreContract } from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { toFixed } from '@celo/utils/lib/fixidity' -import { ElectionInstance } from 'types' - -const initializeArgs = async (): Promise => { - return [ - config.registry.predeployedProxyAddress, - config.election.minElectableValidators, - config.election.maxElectableValidators, - config.election.maxVotesPerAccount, - toFixed(config.election.electabilityThreshold).toFixed(), - ] -} - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.Election, - initializeArgs -) diff --git a/packages/protocol/migrations_ts/15_epoch_rewards.ts b/packages/protocol/migrations_ts/15_epoch_rewards.ts deleted file mode 100644 index 0c6db1fd7..000000000 --- a/packages/protocol/migrations_ts/15_epoch_rewards.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { - deploymentForCoreContract, - getDeployedProxiedContract, -} from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { toFixed } from '@celo/utils/lib/fixidity' -import { EpochRewardsInstance, FreezerInstance } from 'types' - -const initializeArgs = async (): Promise => { - return [ - config.registry.predeployedProxyAddress, - toFixed(config.epochRewards.targetVotingYieldParameters.initial).toFixed(), - toFixed(config.epochRewards.targetVotingYieldParameters.max).toFixed(), - toFixed(config.epochRewards.targetVotingYieldParameters.adjustmentFactor).toFixed(), - toFixed(config.epochRewards.rewardsMultiplierParameters.max).toFixed(), - toFixed(config.epochRewards.rewardsMultiplierParameters.adjustmentFactors.underspend).toFixed(), - toFixed(config.epochRewards.rewardsMultiplierParameters.adjustmentFactors.overspend).toFixed(), - toFixed(config.epochRewards.targetVotingGoldFraction).toFixed(), - config.epochRewards.maxValidatorEpochPayment, - toFixed(config.epochRewards.communityRewardFraction).toFixed(), - config.epochRewards.carbonOffsettingPartner, - toFixed(config.epochRewards.carbonOffsettingFraction).toFixed(), - ] -} - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.EpochRewards, - initializeArgs, - async (epochRewards: EpochRewardsInstance) => { - if (config.epochRewards.frozen) { - const freezer: FreezerInstance = await getDeployedProxiedContract( - 'Freezer', - artifacts - ) - await freezer.freeze(epochRewards.address) - } - } -) diff --git a/packages/protocol/migrations_ts/16_random.ts b/packages/protocol/migrations_ts/16_random.ts deleted file mode 100644 index 0069a349c..000000000 --- a/packages/protocol/migrations_ts/16_random.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { deploymentForCoreContract } from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { RandomInstance } from 'types' - -const initializeArgs = async (_: string): Promise => { - return [config.random.randomnessBlockRetentionWindow] -} - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.Random, - initializeArgs -) diff --git a/packages/protocol/migrations_ts/17_attestations.ts b/packages/protocol/migrations_ts/17_attestations.ts deleted file mode 100644 index 7abb69f26..000000000 --- a/packages/protocol/migrations_ts/17_attestations.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { - convertToContractDecimals, - deploymentForCoreContract, - getDeployedProxiedContract, -} from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { AttestationsInstance } from 'types' -import { StableTokenInstance } from 'types/mento' -import { MENTO_PACKAGE } from '../contractPackages' -import { ArtifactsSingleton } from '../lib/artifactsSingleton' - -const initializeArgs = async (): Promise<[string, string, string, string, string[], string[]]> => { - const stableToken: StableTokenInstance = await getDeployedProxiedContract( - 'StableToken', - ArtifactsSingleton.getInstance(MENTO_PACKAGE) - ) - - const attestationFee = await convertToContractDecimals( - config.attestations.attestationRequestFeeInDollars, - stableToken - ) - return [ - config.registry.predeployedProxyAddress, - config.attestations.attestationExpiryBlocks.toString(), - config.attestations.selectIssuersWaitBlocks.toString(), - config.attestations.maxAttestations.toString(), - [stableToken.address], - [attestationFee.toString()], - ] -} - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.Attestations, - initializeArgs -) diff --git a/packages/protocol/migrations_ts/18_escrow.ts b/packages/protocol/migrations_ts/18_escrow.ts deleted file mode 100644 index 643258b7f..000000000 --- a/packages/protocol/migrations_ts/18_escrow.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { deploymentForCoreContract } from '@celo/protocol/lib/web3-utils' -import { EscrowInstance } from 'types' - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.Escrow, - async () => [] -) diff --git a/packages/protocol/migrations_ts/19_blockchainparams.ts b/packages/protocol/migrations_ts/19_blockchainparams.ts deleted file mode 100644 index f64538a51..000000000 --- a/packages/protocol/migrations_ts/19_blockchainparams.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { deploymentForCoreContract } from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { BlockchainParametersInstance } from 'types' - -const initializeArgs = async (_: string): Promise => { - return [ - config.blockchainParameters.gasForNonGoldCurrencies, - config.blockchainParameters.deploymentBlockGasLimit, - config.blockchainParameters.uptimeLookbackWindow, - ] -} - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.BlockchainParameters, - initializeArgs -) diff --git a/packages/protocol/migrations_ts/20_governance_slasher.ts b/packages/protocol/migrations_ts/20_governance_slasher.ts deleted file mode 100644 index 474950d7b..000000000 --- a/packages/protocol/migrations_ts/20_governance_slasher.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { - deploymentForCoreContract, - getDeployedProxiedContract, -} from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { GovernanceSlasherInstance, LockedGoldInstance } from 'types' - -const initializeArgs = async (_: string): Promise => { - return [config.registry.predeployedProxyAddress] -} - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.GovernanceSlasher, - initializeArgs, - async () => { - console.info('Adding GovernanceSlasher contract as slasher.') - const lockedGold: LockedGoldInstance = await getDeployedProxiedContract( - 'LockedGold', - artifacts - ) - await lockedGold.addSlasher(CeloContractName.GovernanceSlasher) - } -) diff --git a/packages/protocol/migrations_ts/21_double_signing_slasher.ts b/packages/protocol/migrations_ts/21_double_signing_slasher.ts deleted file mode 100644 index 31ffcfee9..000000000 --- a/packages/protocol/migrations_ts/21_double_signing_slasher.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { - deploymentForCoreContract, - getDeployedProxiedContract, -} from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { DoubleSigningSlasherInstance, LockedGoldInstance } from 'types' - -const initializeArgs = async (_: string): Promise => { - return [ - config.registry.predeployedProxyAddress, - config.doubleSigningSlasher.penalty, - config.doubleSigningSlasher.reward, - ] -} - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.DoubleSigningSlasher, - initializeArgs, - async () => { - console.info('Adding DoubleSigningSlasher contract as slasher.') - const lockedGold: LockedGoldInstance = await getDeployedProxiedContract( - 'LockedGold', - artifacts - ) - await lockedGold.addSlasher(CeloContractName.DoubleSigningSlasher) - } -) diff --git a/packages/protocol/migrations_ts/22_downtime_slasher.ts b/packages/protocol/migrations_ts/22_downtime_slasher.ts deleted file mode 100644 index ec729e010..000000000 --- a/packages/protocol/migrations_ts/22_downtime_slasher.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { - deploymentForCoreContract, - getDeployedProxiedContract, -} from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { DowntimeSlasherInstance, LockedGoldInstance } from 'types' - -const initializeArgs = async (_: string): Promise => { - return [ - config.registry.predeployedProxyAddress, - config.downtimeSlasher.penalty, - config.downtimeSlasher.reward, - config.downtimeSlasher.slashableDowntime, - ] -} - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.DowntimeSlasher, - initializeArgs, - async () => { - console.info('Adding DowntimeSlasher contract as slasher.') - const lockedGold: LockedGoldInstance = await getDeployedProxiedContract( - 'LockedGold', - artifacts - ) - await lockedGold.addSlasher(CeloContractName.DowntimeSlasher) - } -) diff --git a/packages/protocol/migrations_ts/23_governance_approver_multisig.ts b/packages/protocol/migrations_ts/23_governance_approver_multisig.ts deleted file mode 100644 index 52dd4b191..000000000 --- a/packages/protocol/migrations_ts/23_governance_approver_multisig.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { - deploymentForProxiedContract, - transferOwnershipOfProxy, -} from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { GovernanceApproverMultiSigInstance } from 'types' - -const initializeArgs = async (): Promise => { - return [ - config.governanceApproverMultiSig.signatories, - config.governanceApproverMultiSig.numRequiredConfirmations, - config.governanceApproverMultiSig.numInternalRequiredConfirmations, - ] -} - -module.exports = deploymentForProxiedContract( - web3, - artifacts, - CeloContractName.GovernanceApproverMultiSig, - initializeArgs, - async (governanceApproverMultiSig: GovernanceApproverMultiSigInstance) => { - await transferOwnershipOfProxy( - CeloContractName.GovernanceApproverMultiSig, - governanceApproverMultiSig.address, - artifacts - ) - } -) diff --git a/packages/protocol/migrations_ts/24_grandamento.ts b/packages/protocol/migrations_ts/24_grandamento.ts deleted file mode 100644 index 5c6e9635d..000000000 --- a/packages/protocol/migrations_ts/24_grandamento.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* tslint:disable:no-console */ - -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { - deploymentForCoreContract, - getDeployedProxiedContract, -} from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { toFixed } from '@celo/utils/lib/fixidity' -import { GrandaMentoInstance, ReserveInstance } from 'types/mento' -import { MENTO_PACKAGE } from '../contractPackages' -import { ArtifactsSingleton } from '../lib/artifactsSingleton' - -const initializeArgs = async (): Promise => { - return [ - config.registry.predeployedProxyAddress, - config.grandaMento.approver, - toFixed(config.grandaMento.maxApprovalExchangeRateChange).toString(), - toFixed(config.grandaMento.spread).toString(), - config.grandaMento.vetoPeriodSeconds, - ] -} - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.GrandaMento, - initializeArgs, - async (grandaMento: GrandaMentoInstance) => { - // Add as a spender of the Reserve - const reserve: ReserveInstance = await getDeployedProxiedContract( - 'Reserve', - ArtifactsSingleton.getInstance(MENTO_PACKAGE) - ) - await reserve.addExchangeSpender(grandaMento.address) - - for (const stableToken of Object.keys(config.grandaMento.stableTokenExchangeLimits)) { - const { min, max } = config.grandaMento.stableTokenExchangeLimits[stableToken] - await grandaMento.setStableTokenExchangeLimits(stableToken, min, max) - } - }, - MENTO_PACKAGE -) diff --git a/packages/protocol/migrations_ts/25_federated_attestations.ts b/packages/protocol/migrations_ts/25_federated_attestations.ts deleted file mode 100644 index 43bace75b..000000000 --- a/packages/protocol/migrations_ts/25_federated_attestations.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { deploymentForCoreContract } from '@celo/protocol/lib/web3-utils' -import { FederatedAttestationsInstance } from 'types' - -const initializeArgs = async () => { - return [] -} - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.FederatedAttestations, - initializeArgs -) diff --git a/packages/protocol/migrations_ts/26_00_mento_fee_handler_seller.ts b/packages/protocol/migrations_ts/26_00_mento_fee_handler_seller.ts deleted file mode 100644 index ffae1b743..000000000 --- a/packages/protocol/migrations_ts/26_00_mento_fee_handler_seller.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { deploymentForCoreContract } from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { MentoFeeHandlerSellerInstance } from 'types' - -const initializeArgs = async () => { - return [config.registry.predeployedProxyAddress, [], []] -} - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.MentoFeeHandlerSeller, - initializeArgs -) diff --git a/packages/protocol/migrations_ts/26_01_uniswap_fee_handler_seller.ts b/packages/protocol/migrations_ts/26_01_uniswap_fee_handler_seller.ts deleted file mode 100644 index 5e1e19268..000000000 --- a/packages/protocol/migrations_ts/26_01_uniswap_fee_handler_seller.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { deploymentForCoreContract } from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { UniswapFeeHandlerSellerInstance } from 'types' - -const initializeArgs = async () => { - return [config.registry.predeployedProxyAddress, [], []] -} - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.UniswapFeeHandlerSeller, - initializeArgs -) diff --git a/packages/protocol/migrations_ts/26_99_fee_handler.ts b/packages/protocol/migrations_ts/26_99_fee_handler.ts deleted file mode 100644 index a9b283db9..000000000 --- a/packages/protocol/migrations_ts/26_99_fee_handler.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { - deploymentForCoreContract, - getDeployedProxiedContract, -} from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { toFixed } from '@celo/utils/lib/fixidity' -import { FeeHandlerInstance, MentoFeeHandlerSellerInstance } from 'types' -import { StableTokenInstance } from 'types/mento' -import { MENTO_PACKAGE } from '../contractPackages' -import { ArtifactsSingleton } from '../lib/artifactsSingleton' - -const initializeArgs = async () => { - return [ - config.registry.predeployedProxyAddress, - config.feeHandler.beneficiaryAddress, - toFixed(config.feeHandler.burnFraction).toString(), - [], - [], - [], - [], - ] -} - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.FeeHandler, - initializeArgs, - async (feeHandler: FeeHandlerInstance) => { - for (const token of ['StableToken', 'StableTokenEUR', 'StableTokenBRL']) { - const stableToken: StableTokenInstance = - await getDeployedProxiedContract( - token, - ArtifactsSingleton.getInstance(MENTO_PACKAGE) - ) - - const mentoFeeHandlerSeller: MentoFeeHandlerSellerInstance = - await getDeployedProxiedContract( - CeloContractName.MentoFeeHandlerSeller, - artifacts - ) - - await feeHandler.addToken(stableToken.address, mentoFeeHandlerSeller.address) - } - } -) diff --git a/packages/protocol/migrations_ts/27_odispayments.ts b/packages/protocol/migrations_ts/27_odispayments.ts deleted file mode 100644 index 947b95214..000000000 --- a/packages/protocol/migrations_ts/27_odispayments.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { deploymentForCoreContract } from '@celo/protocol/lib/web3-utils' -import { OdisPaymentsInstance } from 'types' - -const initializeArgs = async () => { - return [] -} - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.OdisPayments, - initializeArgs -) diff --git a/packages/protocol/migrations_ts/28_governance.ts b/packages/protocol/migrations_ts/28_governance.ts deleted file mode 100644 index 1410c95fa..000000000 --- a/packages/protocol/migrations_ts/28_governance.ts +++ /dev/null @@ -1,156 +0,0 @@ -/* tslint:disable:no-console */ - -import { constitution } from '@celo/protocol/governanceConstitution' -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { - deploymentForCoreContract, - getDeployedProxiedContract, - getFunctionSelectorsForContractProxy, - transferOwnershipOfProxyAndImplementation, -} from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { toFixed } from '@celo/utils/lib/fixidity' -import { GovernanceApproverMultiSigInstance, GovernanceInstance } from 'types' -import { MENTO_PACKAGE, SOLIDITY_08_PACKAGE } from '../contractPackages' - -import { ArtifactsSingleton } from '../lib/artifactsSingleton' - -const initializeArgs = async (networkName: string): Promise => { - const governanceApproverMultiSig: GovernanceApproverMultiSigInstance = - await getDeployedProxiedContract( - CeloContractName.GovernanceApproverMultiSig, - artifacts - ) - const networkFrom: string = require('@celo/protocol/truffle-config.js').networks[networkName].from - const approver: string = config.governanceApproverMultiSig.useMultiSig - ? governanceApproverMultiSig.address - : networkFrom - - return [ - config.registry.predeployedProxyAddress, - approver, - config.governance.concurrentProposals, - web3.utils.toWei(config.governance.minDeposit.toString(), 'ether'), - config.governance.queueExpiry, - config.governance.dequeueFrequency, - config.governance.referendumStageDuration, - config.governance.executionStageDuration, - toFixed(config.governance.participationBaseline).toString(), - toFixed(config.governance.participationBaselineFloor).toString(), - toFixed(config.governance.participationBaselineUpdateFactor).toString(), - toFixed(config.governance.participationBaselineQuorumFactor).toString(), - ] -} - -module.exports = deploymentForCoreContract( - web3, - artifacts, - CeloContractName.Governance, - initializeArgs, - async (governance: GovernanceInstance) => { - if (!config.governance.skipSetConstitution) { - console.info('Setting constitution thresholds') - const constitutionContractNames = Object.keys(constitution).filter( - (contractName) => contractName !== 'proxy' - ) - - for (const contractName of constitutionContractNames) { - console.log(`\tSetting constitution thresholds for ${contractName}`) - - const artifactsObject = ArtifactsSingleton.getInstance( - constitution[contractName].__contractPackage, - artifacts - ) - - const contract = await getDeployedProxiedContract( - contractName, - artifactsObject - ) - - const selectors = getFunctionSelectorsForContractProxy( - contract, - artifactsObject.getProxy(contractName, artifacts), - web3 - ) - - selectors.default = ['0x00000000'] - const thresholds = { ...constitution.proxy, ...constitution[contractName] } - - const tresholdKeys = Object.keys(thresholds).filter( - (method) => method !== '__contractPackage' - ) - - for (const func of tresholdKeys) { - await Promise.all( - selectors[func].map((selector) => - governance.setConstitution(contract.address, selector, toFixed(thresholds[func])) - ) - ) - } - } - } - - // This list probably needs a refactor - const proxyAndImplementationOwnedByGovernance = [ - { - contracts: [ - 'Accounts', - 'Attestations', - // BlockchainParameters ownership transitioned to governance in a follow-up script. - // 'BlockchainParameters', - 'DoubleSigningSlasher', - 'DowntimeSlasher', - 'Election', - 'EpochRewards', - 'Escrow', - 'FederatedAttestations', - 'FeeCurrencyWhitelist', - 'Freezer', - 'FeeHandler', - 'GoldToken', - 'Governance', - 'GovernanceSlasher', - 'LockedGold', - 'OdisPayments', - 'Random', - 'Registry', - 'SortedOracles', - 'Validators', - ], - }, - { - contracts: [ - 'Exchange', - 'ExchangeEUR', - 'ExchangeBRL', - 'GrandaMento', - 'Reserve', - 'StableToken', - 'StableTokenEUR', - 'StableTokenBRL', - ], - __contractPackage: MENTO_PACKAGE, - }, - { - contracts: ['GasPriceMinimum'], - __contractPackage: SOLIDITY_08_PACKAGE, - }, - ] - - if (!config.governance.skipTransferOwnership) { - for (const contractPackage of proxyAndImplementationOwnedByGovernance) { - const artifactsInstance = ArtifactsSingleton.getInstance( - contractPackage.__contractPackage, - artifacts - ) - for (const contractName of contractPackage.contracts) { - await transferOwnershipOfProxyAndImplementation( - contractName, - governance.address, - artifactsInstance - ) - } - } - } - } -) diff --git a/packages/protocol/migrations_ts/29_elect_validators.ts b/packages/protocol/migrations_ts/29_elect_validators.ts deleted file mode 100644 index 742fff479..000000000 --- a/packages/protocol/migrations_ts/29_elect_validators.ts +++ /dev/null @@ -1,404 +0,0 @@ -/* tslint:disable:no-console */ -import { NULL_ADDRESS } from '@celo/base/lib/address' -import { CeloTxObject } from '@celo/connect' -import { getBlsPoP, getBlsPublicKey } from '@celo/cryptographic-utils/lib/bls' -import { - getDeployedProxiedContract, - sendTransactionWithPrivateKey, -} from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { privateKeyToAddress, privateKeyToPublicKey } from '@celo/utils/lib/address' -import { toFixed } from '@celo/utils/lib/fixidity' -import { signMessage } from '@celo/utils/lib/signatureUtils' -import { BigNumber } from 'bignumber.js' -import { AccountsInstance, ElectionInstance, LockedGoldInstance, ValidatorsInstance } from 'types' -import Web3 from 'web3' - -const truffle = require('@celo/protocol/truffle-config.js') -const bip39 = require('bip39') -const hdkey = require('ethereumjs-wallet/hdkey') - -function ganachePrivateKey(num) { - const seed = bip39.mnemonicToSeedSync(truffle.networks.development.mnemonic) - const hdk = hdkey.fromMasterSeed(seed) - const addrNode = hdk.derivePath("m/44'/60'/0'/0/" + num) // m/44'/60'/0'/0/0 is derivation path for the first account. m/44'/60'/0'/0/1 is the derivation path for the second account and so on - return addrNode.getWallet().getPrivateKey().toString('hex') -} - -function serializeKeystore(keystore: any) { - return Buffer.from(JSON.stringify(keystore)).toString('base64') -} - -let isGanache = false - -// Will include Ganache private keys for accounts 7-9, used for group keys -let extraKeys = [] - -async function sendTransaction( - web3: Web3, - tx: CeloTxObject | null, - privateKey: string, - txArgs: any -) { - if (isGanache) { - const from = privateKeyToAddress(privateKey) - if (tx == null) { - await web3.eth.sendTransaction({ ...txArgs, from }) - } else { - await tx.send({ ...txArgs, from, gasLimit: '10000000' }) - } - } else { - await sendTransactionWithPrivateKey(web3, tx, privateKey, txArgs) - } -} - -async function lockGold( - accounts: AccountsInstance, - lockedGold: LockedGoldInstance, - value: BigNumber, - privateKey: string -) { - // @ts-ignore - const createAccountTx = accounts.contract.methods.createAccount() - await sendTransaction(web3, createAccountTx, privateKey, { - to: accounts.address, - }) - - // @ts-ignore - const lockTx = lockedGold.contract.methods.lock() - - await sendTransaction(web3, lockTx, privateKey, { - to: lockedGold.address, - value: value.toString(10), - }) -} - -function createAccountOrUseFromGanache() { - if (isGanache) { - const privateKey = extraKeys.pop() - return { address: privateKeyToAddress(privateKey), privateKey } - } else { - return web3.eth.accounts.create() - } -} - -async function registerValidatorGroup( - name: string, - accounts: AccountsInstance, - lockedGold: LockedGoldInstance, - validators: ValidatorsInstance, - privateKey: string, - lockedGoldValue: BigNumber -) { - // Validators can't also be validator groups, so we create a new account to register the - // validator group with, and set the name of the group account to the private key of this account - // encrypted with the private key of the first validator, so that the group private key - // can be recovered. - const account = createAccountOrUseFromGanache() - - // We do not use web3 provided by Truffle since the eth.accounts.encrypt behaves differently - // in the version we use elsewhere. - const encryptionWeb3 = new Web3('http://localhost:8545') - const encryptedPrivateKey = encryptionWeb3.eth.accounts.encrypt(account.privateKey, privateKey) - const encodedKey = serializeKeystore(encryptedPrivateKey) - - // Add a premium to cover tx fees - const v = lockedGoldValue.times(1.01).integerValue() - - console.info(` - send funds ${v} to group address ${account.address}}`) - await sendTransaction(web3, null, privateKey, { - to: account.address, - value: v, - }) - - console.info(` - lock gold`) - await lockGold(accounts, lockedGold, lockedGoldValue, account.privateKey) - - console.info(` - setName`) - // @ts-ignore - const setNameTx = accounts.contract.methods.setName(`${name} ${encodedKey}`) - await sendTransaction(web3, setNameTx, account.privateKey, { - to: accounts.address, - }) - - console.info(` - registerValidatorGroup`) - // @ts-ignore - const tx = validators.contract.methods.registerValidatorGroup( - toFixed(config.validators.commission).toString() - ) - - await sendTransaction(web3, tx, account.privateKey, { - to: validators.address, - }) - - return account -} - -async function registerValidator( - accounts: AccountsInstance, - lockedGold: LockedGoldInstance, - validators: ValidatorsInstance, - validatorPrivateKey: string, - attestationKey: string, - groupAddress: string, - index: number, - networkName: string -) { - const valName = `CLabs Validator #${index} on ${networkName}` - - console.info(` - lockGold ${valName}`) - await lockGold( - accounts, - lockedGold, - config.validators.validatorLockedGoldRequirements.value, - validatorPrivateKey - ) - - console.info(` - setName ${valName}`) - - // @ts-ignore - const setNameTx = accounts.contract.methods.setName(valName) - await sendTransaction(web3, setNameTx, validatorPrivateKey, { - to: accounts.address, - }) - - console.info(` - registerValidator ${valName}`) - const publicKey = privateKeyToPublicKey(validatorPrivateKey) - const blsPublicKey = getBlsPublicKey(validatorPrivateKey) - const blsPoP = getBlsPoP(privateKeyToAddress(validatorPrivateKey), validatorPrivateKey) - - // @ts-ignore - const registerTx = validators.contract.methods.registerValidator(publicKey, blsPublicKey, blsPoP) - - await sendTransaction(web3, registerTx, validatorPrivateKey, { - to: validators.address, - }) - - console.info(` - affiliate ${valName}`) - - // @ts-ignore - const affiliateTx = validators.contract.methods.affiliate(groupAddress) - - await sendTransaction(web3, affiliateTx, validatorPrivateKey, { - to: validators.address, - }) - - console.info(` - setAccountDataEncryptionKey ${valName}`) - - // @ts-ignore - const registerDataEncryptionKeyTx = accounts.contract.methods.setAccountDataEncryptionKey( - privateKeyToPublicKey(validatorPrivateKey) - ) - - await sendTransaction(web3, registerDataEncryptionKeyTx, validatorPrivateKey, { - to: accounts.address, - }) - - if (!isGanache) { - // Authorize the attestation signer - const attestationKeyAddress = privateKeyToAddress(attestationKey) - console.info(` - authorizeAttestationSigner ${valName}->${attestationKeyAddress}`) - const message = web3.utils.soliditySha3({ - type: 'address', - value: privateKeyToAddress(validatorPrivateKey), - }) - const signature = signMessage(message, attestationKey, attestationKeyAddress) - - // @ts-ignore - const registerAttestationKeyTx = accounts.contract.methods.authorizeAttestationSigner( - attestationKeyAddress, - signature.v, - signature.r, - signature.s - ) - - await sendTransaction(web3, registerAttestationKeyTx, validatorPrivateKey, { - to: accounts.address, - }) - } - - console.info(` - done ${valName}`) - return -} - -module.exports = async (_deployer: any, networkName: string) => { - const accounts: AccountsInstance = await getDeployedProxiedContract( - 'Accounts', - artifacts - ) - - const validators: ValidatorsInstance = await getDeployedProxiedContract( - 'Validators', - artifacts - ) - - const lockedGold: LockedGoldInstance = await getDeployedProxiedContract( - 'LockedGold', - artifacts - ) - - const election: ElectionInstance = await getDeployedProxiedContract( - 'Election', - artifacts - ) - - if (networkName === 'development') { - isGanache = true - const addr0 = privateKeyToAddress('0x' + ganachePrivateKey(0)) - for (let i = 10; i < 36; i++) { - const key = '0x' + ganachePrivateKey(i) - const addr = privateKeyToAddress(key) - // @ts-ignore - await web3.eth.personal.importRawKey(key, 'passphrase') - await web3.eth.personal.unlockAccount(addr, 'passphrase', 1000000) - await web3.eth.sendTransaction({ from: addr0, to: addr, value: new BigNumber(11000e18) }) - } - config.validators.validatorKeys = [...Array(30)].map((_, i) => ganachePrivateKey(i)) - extraKeys = [...Array(6)].map((_, i) => ganachePrivateKey(i + 30)) - config.validators.attestationKeys = config.validators.validatorKeys - } - - const valKeys: string[] = config.validators.validatorKeys - const attestationKeys: string[] = config.validators.attestationKeys - - if (valKeys.length === 0) { - console.info(' No validators to register') - return - } - - if (config.validators.votesRatioOfLastVsFirstGroup < 1) { - throw new Error(`votesRatioOfLastVsFirstGroup needs to be >= 1`) - } - - // Assumptions about where funds are located: - // * Validator 0 holds funds for all groups' stakes - // * Validator 1-n holds funds needed for their own stake - const validator0Key = valKeys[0] - - if (valKeys.length < parseInt(config.election.minElectableValidators, 10)) { - console.info( - ` Warning: Have ${valKeys.length} Validator keys but require a minimum of ${config.election.minElectableValidators} Validators in order for a new validator set to be elected.` - ) - } - - // Split the validator keys into groups that will fit within the max group size. - const valKeyGroups: string[][] = [] - const maxGroupSize: number = Number(config.validators.maxGroupSize) - for (let i = 0; i < valKeys.length; i += maxGroupSize) { - valKeyGroups.push(valKeys.slice(i, Math.min(i + maxGroupSize, valKeys.length))) - } - - // Calculate per validator locked gold for first group... - const lockedGoldPerValAtFirstGroup = new BigNumber( - config.validators.groupLockedGoldRequirements.value - ) - // ...and the delta for each subsequent group - const lockedGoldPerValEachGroup = new BigNumber( - config.validators.votesRatioOfLastVsFirstGroup - 1 - ) - .times(lockedGoldPerValAtFirstGroup) - .div(Math.max(valKeyGroups.length - 1, 1)) - .integerValue() - - const groups = valKeyGroups.map((keys, i) => { - const lockedGoldAmount = lockedGoldPerValAtFirstGroup - .plus(lockedGoldPerValEachGroup.times(i)) - .times(keys.length) - return { - valKeys: keys, - name: valKeyGroups.length - ? config.validators.groupName + `(${i + 1})` - : config.validators.groupName, - lockedGold: lockedGoldAmount, - voteAmount: - i === 0 || i === valKeyGroups.length - 1 - ? lockedGoldAmount - : new BigNumber(config.validators.groupLockedGoldRequirements.value), - account: null, - } - }) - - for (const [idx, group] of groups.entries()) { - console.info( - ` Registering validator group: ${group.name} with: ${group.lockedGold} CG locked...` - ) - group.account = await registerValidatorGroup( - group.name, - accounts, - lockedGold, - validators, - validator0Key, - group.lockedGold - ) - - console.info(` * Registering ${group.valKeys.length} validators ...`) - await Promise.all( - group.valKeys.map((key, i) => { - const index = idx * config.validators.maxGroupSize + i - return registerValidator( - accounts, - lockedGold, - validators, - key, - attestationKeys[index], - group.account.address, - index, - networkName - ) - }) - ) - - console.info(` * Adding Validators to ${group.name} ...`) - for (const [i, key] of group.valKeys.entries()) { - const address = privateKeyToAddress(key) - console.info(` - Adding ${address} ...`) - if (i === 0) { - const groupsWithVotes = groups.slice(0, idx) - groupsWithVotes.sort((a, b) => a.voteAmount.comparedTo(b.voteAmount)) - - // @ts-ignore - const addTx = validators.contract.methods.addFirstMember( - address, - NULL_ADDRESS, - groupsWithVotes.length ? groupsWithVotes[0].account.address : NULL_ADDRESS - ) - await sendTransaction(web3, addTx, group.account.privateKey, { - to: validators.address, - }) - } else { - // @ts-ignore - const addTx = validators.contract.methods.addMember(address) - await sendTransaction(web3, addTx, group.account.privateKey, { - to: validators.address, - }) - } - } - - // Determine the lesser and greater group addresses after voting. - const sortedGroups = groups.slice(0, idx + 1) - sortedGroups.sort((a, b) => a.voteAmount.comparedTo(b.voteAmount)) - const groupSortedIndex = sortedGroups.indexOf(group) - const lesser = - groupSortedIndex > 0 ? sortedGroups[groupSortedIndex - 1].account.address : NULL_ADDRESS - const greater = - groupSortedIndex < idx ? sortedGroups[groupSortedIndex + 1].account.address : NULL_ADDRESS - - // Note: Only the groups vote for themselves here. The validators do not vote. - console.info(' * Group voting for itself ...') - - // Make first and last group high votes so we can maintain presence. - const voteAmount = '0x' + group.voteAmount.toString(16) - - // @ts-ignore - const voteTx = election.contract.methods.vote( - group.account.address, - voteAmount, - lesser, - greater - ) - await sendTransaction(web3, voteTx, group.account.privateKey, { - to: election.address, - }) - } - console.log('Done with migrations') -} diff --git a/packages/protocol/package.json b/packages/protocol/package.json deleted file mode 100644 index b84b1ddaf..000000000 --- a/packages/protocol/package.json +++ /dev/null @@ -1,139 +0,0 @@ -{ - "name": "@celo/protocol", - "version": "1.0.2", - "private": true, - "main": "index.ts", - "author": "Celo", - "license": "LGPL-3.0", - "scripts": { - "lint:ts": "tslint -c tslint.json --project tsconfig.json", - "lint:sol": "solhint './contracts/**/*.sol'", - "lint": "yarn run lint:ts && yarn run lint:sol", - "clean": "rm -rf ./types/typechain && rm -rf build/* && rm -rf .0x-artifacts/* && rm -rf migrations/*.js* && rm -rf migrations_ts/*.js* && rm -rf test/**/*.js* && rm -f lib/*.js* && rm -f lib/**/*.js* && rm -f scripts/*.js* && yarn clean:foundry", - "clean:foundry": "rm -rf cache out", - "test": "rm test/**/*.js ; node runTests.js", - "quicktest": "./scripts/bash/quicktest.sh", - "test:coverage": "yarn run test --coverage", - "ci:test-make-release": "./scripts/bash/release-on-devchain.sh", - "test:release-snapshots": "./scripts/bash/release-snapshots.sh", - "test:generate-old-devchain-and-build": "./scripts/bash/generate-old-devchain-and-build.sh", - "build:ts": "rm -f migrations/*.js* && ts-node --preferTsExts ./scripts/build.ts --truffleTypes ./types/typechain && tsc -b && mv migrations_ts/*.js* migrations", - "gas": "yarn run test --gas", - "pull-submodules": "git submodule update --init --recursive", - "delete-submodules": "rm -rf $(git submodule | awk '{ print $2 }')", - "build:sol": "yarn pull-submodules && mkdir -p migrations && ts-node --preferTsExts ./scripts/build.ts --solidity ${BUILD_DIR:-./build}", - "build": "yarn build:sol && yarn build:ts", - "prebuild": "rm -rf ./build", - "is_contract_release": "ts-node ./scripts/is-contract-release.ts", - "prepare_contracts_and_abis_publishing": "ts-node ./scripts/prepare-contracts-and-abis-publishing.ts", - "sourcify-publish": "ts-node ./scripts/sourcify-publish.ts", - "migrate": "./scripts/bash/migrate.sh", - "set_block_gas_limit": "./scripts/bash/set_block_gas_limit.sh", - "download-artifacts": "./scripts/bash/download_artifacts.sh", - "init-network": "./scripts/bash/init_network.sh", - "upload-artifacts": "./scripts/bash/upload_artifacts.sh", - "upgrade": "./scripts/bash/upgrade.sh", - "revoke": "./scripts/bash/revoke.sh", - "govern": "./scripts/bash/govern.sh", - "console": "./scripts/bash/console.sh", - "check-versions": "./scripts/bash/check-versions.sh", - "check-opcodes": "ts-node scripts/check-opcodes.ts", - "make-release": "./scripts/bash/make-release.sh", - "verify-deployed": "./scripts/bash/verify-deployed.sh", - "verify-release": "./scripts/bash/verify-release.sh", - "ganache-dev": "./scripts/bash/ganache.sh", - "ganache-devchain": "./scripts/bash/ganache_devchain.sh", - "truffle:migrate": "truffle migrate", - "devchain": "ts-node scripts/devchain.ts", - "devchain:reset": "yarn devchain generate-tar .tmp/devchain.tar.gz --upto 28", - "view-tags": "git for-each-ref 'refs/tags/core-contracts.*' --sort=-committerdate --format='%(color:magenta)%(committerdate:short) %(color:blue)%(tree) %(color:green)github.com/celo-org/celo-monorepo/releases/tag/%(color:yellow)%(refname:short)'", - "generate-stabletoken-files": "ts-node ./scripts/generate-stabletoken-files.ts", - "truffle-verify": "yarn truffle run verify" - }, - "dependencies": { - "@0x/sol-compiler": "^4.8.3", - "@0x/sol-coverage": "^4.0.47", - "@0x/sol-profiler": "^4.1.37", - "@0x/sol-trace": "^3.0.47", - "@0x/subproviders": "^7.0.1", - "@celo/base": "^6.0.0", - "@celo/bls12377js": "0.1.1", - "@celo/connect": "^5.1.1", - "@celo/cryptographic-utils": "^5.0.6", - "@celo/utils": "^5.0.6", - "@celo/wallet-local": "^5.1.1", - "@ethereumjs/util": "8.0.5", - "@ethereumjs/vm": "npm:@celo/ethereumjs-vm@6.4.1-unofficial.0", - "@ganache/console.log": "0.3.0", - "@openzeppelin/contracts8": "npm:@openzeppelin/contracts@^4.4.2", - "@openzeppelin/upgrades": "^2.8.0", - "@summa-tx/memview.sol": "^1.1.0", - "@truffle/artifactor": "4.0.180", - "@truffle/contract": "4.6.10", - "@truffle/resolver": "9.0.27", - "bignumber.js": "9.1.0", - "bip39": "https://github.com/bitcoinjs/bip39#d8ea080a18b40f301d4e2219a2991cd2417e83c2", - "bn.js": "^5.1.0", - "chai": "^4.3.6", - "chai-subset": "^1.6.0", - "chalk": "^2.4.2", - "csv-parser": "^2.0.0", - "csv-stringify": "^4.3.1", - "elliptic": "^6.5.4", - "ethereum-cryptography": "1.2.0", - "ethereumjs-abi": "^0.6.8", - "ethereumjs-wallet": "^0.6.3", - "form-data": "^3.0.0", - "fs-extra": "^5.0.0", - "ganache": "npm:@celo/ganache@7.8.0-unofficial.0", - "glob-fs": "^0.1.7", - "graphql": "^14.1.1", - "j6": "^1.0.2", - "lodash": "^4.17.21", - "mathjs": "^5.0.4", - "minimist": "^1.2.0", - "node-fetch": "^2.6.9", - "openzeppelin-solidity": "^2.5.0", - "prompts": "^2.0.1", - "solhint": "^2.3.1", - "solidity-bytes-utils": "0.0.7", - "truffle": "5.9.0", - "truffle-security": "^1.7.3", - "weak-map": "^1.0.5", - "web3": "1.10.0", - "web3-core": "1.10.0", - "web3-core-helpers": "1.10.0", - "web3-provider-engine": "^16.0.5", - "web3-utils": "1.10.0", - "truffle-plugin-verify": "^0.6.5" - }, - "devDependencies": { - "@celo/odis-identifiers": "^1.0.0", - "@celo/typechain-target-web3-v1-celo": "^1.0.0", - "@celo/typescript": "0.0.1", - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.1.3", - "@types/chai-subset": "1.3.3", - "@types/lodash": "^4.14.199", - "@types/mathjs": "^4.4.1", - "@types/mocha": "^7.0.2", - "@types/targz": "^1.0.0", - "@types/tmp": "^0.1.0", - "@types/yargs": "^13.0.2", - "@wagmi/cli": "^1.0.1", - "cross-env": "^5.1.6", - "eth-gas-reporter": "^0.2.16", - "merkle-patricia-tree": "4.0.0", - "rimraf": "^5.0.5", - "semver": "^7.5.4", - "targz": "^1.0.1", - "tmp": "^0.1.0", - "truffle-typings": "^1.0.6", - "ts-node": "^10.9.1", - "ts-generator": "^0.0.8", - "typechain": "^4.0.3", - "typechain-target-truffle": "^1.0.2", - "typechain-target-ethers-v5": "^5.0.1", - "yargs": "^14.0.0" - } -} diff --git a/packages/protocol/release-9-proposal.json b/packages/protocol/release-9-proposal.json deleted file mode 100644 index 5abc0e68d..000000000 --- a/packages/protocol/release-9-proposal.json +++ /dev/null @@ -1,80 +0,0 @@ -[ - { - "contract": "AttestationsProxy", - "address": "0xdC553892cdeeeD9f575aa0FBA099e5847fd88D20", - "function": "_setImplementation", - "args": [ - "0x5729126891355E3C2626338151Dd50Cc0415E071" - ], - "params": { - "__length__": 1, - "implementation": "0x5729126891355E3C2626338151Dd50Cc0415E071" - }, - "value": "0" - }, - { - "contract": "ElectionProxy", - "address": "0x8D6677192144292870907E3Fa8A5527fE55A7ff6", - "function": "_setImplementation", - "args": [ - "0xCdE5039e3AcB3483aEebEBd59Cf6936056c455D4" - ], - "params": { - "__length__": 1, - "implementation": "0xCdE5039e3AcB3483aEebEBd59Cf6936056c455D4" - }, - "value": "0" - }, - { - "contract": "GoldTokenProxy", - "address": "0x471EcE3750Da237f93B8E339c536989b8978a438", - "function": "_setImplementation", - "args": [ - "0xcB8710e072aC4700eE7eD0C63B2f2102366a7a39" - ], - "params": { - "__length__": 1, - "implementation": "0xcB8710e072aC4700eE7eD0C63B2f2102366a7a39" - }, - "value": "0" - }, - { - "contract": "GovernanceProxy", - "address": "0xD533Ca259b330c7A88f74E000a3FaEa2d63B7972", - "function": "_setImplementation", - "args": [ - "0xf2d7AA9dd1870b2e5BE16643B9E1Bcb5C624cB13" - ], - "params": { - "__length__": 1, - "implementation": "0xf2d7AA9dd1870b2e5BE16643B9E1Bcb5C624cB13" - }, - "value": "0" - }, - { - "contract": "LockedGoldProxy", - "address": "0x6cC083Aed9e3ebe302A6336dBC7c921C9f03349E", - "function": "_setImplementation", - "args": [ - "0x5EAF009ca7c3dF8601bc36A6563b0af76964F4d2" - ], - "params": { - "__length__": 1, - "implementation": "0x5EAF009ca7c3dF8601bc36A6563b0af76964F4d2" - }, - "value": "0" - }, - { - "contract": "ValidatorsProxy", - "address": "0xaEb865bCa93DdC8F47b8e29F40C5399cE34d0C58", - "function": "_setImplementation", - "args": [ - "0x4B84c7507A7AB2af219b9Abd8bCB404F9FB71428" - ], - "params": { - "__length__": 1, - "implementation": "0x4B84c7507A7AB2af219b9Abd8bCB404F9FB71428" - }, - "value": "0" - } -] \ No newline at end of file diff --git a/packages/protocol/releaseData/README.md b/packages/protocol/releaseData/README.md deleted file mode 100644 index 8c1627ada..000000000 --- a/packages/protocol/releaseData/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# Release data - -This directory contains metadata about previous releases of the Celo Core -Contracts. - -## `initializationData/` - -This subdirectory contains, for each core contracts release, the JSON file with -arguments to newly deployed contracts. - -## `versionReports/` - -This subdirectory contains the version reports output by the `check-versions` -script between each successive major release. They are used by the -`protocol-test-release-snapshots` CI job as a regression snapshot test for the -`check-versions` script, so the `oldArtifactsFolder` and `newArtifactsFolder` -should be set to paths that CircleCI jobs use (`/home/circleci/app/...`, see one -of the files for an example). - -## `nonstandard/` - -This will include release data for any contracts releases that didn't follow the -standard release process. - -### `releaseBRL.json` - -This file is the initialization data used when deploying the `cREAL` -stable token. The release occured between Core Contracts releases 5 and 6 and -didn't exactly follow the release process. diff --git a/packages/protocol/releaseData/initializationData/release1.json b/packages/protocol/releaseData/initializationData/release1.json deleted file mode 100644 index 1c0cb9618..000000000 --- a/packages/protocol/releaseData/initializationData/release1.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "DowntimeSlasher": ["0x000000000000000000000000000000000000ce10", "100000000000000000000", "10000000000000000000", "8640"] -} diff --git a/packages/protocol/releaseData/initializationData/release10.json b/packages/protocol/releaseData/initializationData/release10.json deleted file mode 100644 index a2e5c2681..000000000 --- a/packages/protocol/releaseData/initializationData/release10.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "FeeHandler": ["0x000000000000000000000000000000000000ce10", "0x0000000000000000000000000000000000000000", "800000000000000000000000", [],[],[],[]], - "MentoFeeHandlerSeller": ["0x000000000000000000000000000000000000ce10", [], []], - "UniswapFeeHandlerSeller": ["0x000000000000000000000000000000000000ce10", [], []] -} \ No newline at end of file diff --git a/packages/protocol/releaseData/initializationData/release11.json b/packages/protocol/releaseData/initializationData/release11.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/packages/protocol/releaseData/initializationData/release11.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/packages/protocol/releaseData/initializationData/release2.json b/packages/protocol/releaseData/initializationData/release2.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/packages/protocol/releaseData/initializationData/release2.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/packages/protocol/releaseData/initializationData/release3.json b/packages/protocol/releaseData/initializationData/release3.json deleted file mode 100644 index a5e9d99a4..000000000 --- a/packages/protocol/releaseData/initializationData/release3.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "StableTokenEUR": ["Celo Euro", "cEUR", 18, "0x000000000000000000000000000000000000ce10", "1000000000000000000000000", "47304000", ["0xD533Ca259b330c7A88f74E000a3FaEa2d63B7972", "0x989e1a3B344A43911e02cCC609D469fbc15AB1F1"], ["2000000000000000000000000", "6000000000000000000000000"], "ExchangeEUR"], - "ExchangeEUR": ["0x000000000000000000000000000000000000ce10", "0x0000000000000000000000000000000000000000", "5000000000000000000000", "1300000000000000000000", "300", "5"] -} diff --git a/packages/protocol/releaseData/initializationData/release4.json b/packages/protocol/releaseData/initializationData/release4.json deleted file mode 100644 index 0967ef424..000000000 --- a/packages/protocol/releaseData/initializationData/release4.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/packages/protocol/releaseData/initializationData/release5.json b/packages/protocol/releaseData/initializationData/release5.json deleted file mode 100644 index 9389b57ca..000000000 --- a/packages/protocol/releaseData/initializationData/release5.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "GrandaMento": ["0x000000000000000000000000000000000000ce10", "0x0000000000000000000000000000000000000000", "300000000000000000000000", "0", "1209600"] -} diff --git a/packages/protocol/releaseData/initializationData/release6.json b/packages/protocol/releaseData/initializationData/release6.json deleted file mode 100644 index b3e85ae1f..000000000 --- a/packages/protocol/releaseData/initializationData/release6.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "StableTokenBRL": ["Celo Brazilian Real", "cREAL", 18, "0x000000000000000000000000000000000000ce10", "1000000000000000000000000", "47304000", [], [], "ExchangeBRL"], - "ExchangeBRL": ["0x000000000000000000000000000000000000ce10", "0x0000000000000000000000000000000000000000", "5000000000000000000000", "250000000000000000000", "300", "5"] -} \ No newline at end of file diff --git a/packages/protocol/releaseData/initializationData/release7.json b/packages/protocol/releaseData/initializationData/release7.json deleted file mode 100644 index 0967ef424..000000000 --- a/packages/protocol/releaseData/initializationData/release7.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/packages/protocol/releaseData/initializationData/release8.json b/packages/protocol/releaseData/initializationData/release8.json deleted file mode 100644 index aa3ba082d..000000000 --- a/packages/protocol/releaseData/initializationData/release8.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "FederatedAttestations": [], - "OdisPayments": [] -} diff --git a/packages/protocol/releaseData/initializationData/release9.json b/packages/protocol/releaseData/initializationData/release9.json deleted file mode 100644 index 7a73a41bf..000000000 --- a/packages/protocol/releaseData/initializationData/release9.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} \ No newline at end of file diff --git a/packages/protocol/releaseData/nonstandard/baklavaUpdate.json b/packages/protocol/releaseData/nonstandard/baklavaUpdate.json deleted file mode 100644 index 2ca0978aa..000000000 --- a/packages/protocol/releaseData/nonstandard/baklavaUpdate.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "GrandaMento": ["0x000000000000000000000000000000000000ce10", "0x0Cc59Ed03B3e763c02d54D695FFE353055f1502D", "300000000000000000000000", "0", "1209600"], - "StableTokenBRL": ["Celo Brazilian Real", "cREAL", 18, "0x000000000000000000000000000000000000ce10", "1000000000000000000000000", "47304000", [], [], "ExchangeBRL"], - "ExchangeBRL": ["0x000000000000000000000000000000000000ce10", "StableTokenBRL", "5000000000000000000000", "250000000000000000000", "300", "5"], - "FederatedAttestations": [], - "OdisPayments": [] -} \ No newline at end of file diff --git a/packages/protocol/releaseData/nonstandard/releaseBRL.json b/packages/protocol/releaseData/nonstandard/releaseBRL.json deleted file mode 100644 index b3e85ae1f..000000000 --- a/packages/protocol/releaseData/nonstandard/releaseBRL.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "StableTokenBRL": ["Celo Brazilian Real", "cREAL", 18, "0x000000000000000000000000000000000000ce10", "1000000000000000000000000", "47304000", [], [], "ExchangeBRL"], - "ExchangeBRL": ["0x000000000000000000000000000000000000ce10", "0x0000000000000000000000000000000000000000", "5000000000000000000000", "250000000000000000000", "300", "5"] -} \ No newline at end of file diff --git a/packages/protocol/releaseData/versionReports/nonstandar/baklava_fix_report_report.json b/packages/protocol/releaseData/versionReports/nonstandar/baklava_fix_report_report.json deleted file mode 100644 index 7aba93a17..000000000 --- a/packages/protocol/releaseData/versionReports/nonstandar/baklava_fix_report_report.json +++ /dev/null @@ -1,840 +0,0 @@ -{ - "oldArtifactsFolder": "/Users/martinvol/celo/celo-monorepo/packages/protocol/build/core-contracts.v3/contracts", - "newArtifactsFolder": "/Users/martinvol/celo/celo-monorepo/packages/protocol/build/core-contracts.v8/contracts", - "exclude": "/.*Test|Mock.*|I[A-Z].*|.*Proxy|MultiSig.*|ReleaseGold|SlasherUtil|UsingPrecompiles/", - "report": { - "contracts": { - "Escrow": { - "changes": { - "storage": [], - "major": [ - { - "contract": "Escrow", - "signature": "setRegistry(address)", - "type": "MethodRemoved" - }, - { - "contract": "Escrow", - "signature": "initialize(address)", - "type": "MethodRemoved" - } - ], - "minor": [ - { - "contract": "Escrow", - "signature": "transferWithTrustedIssuers(bytes32,address,uint256,uint256,address,uint256,address[])", - "type": "MethodAdded" - }, - { - "contract": "Escrow", - "signature": "getTrustedIssuersPerPayment(address)", - "type": "MethodAdded" - }, - { - "contract": "Escrow", - "signature": "getDefaultTrustedIssuers()", - "type": "MethodAdded" - }, - { - "contract": "Escrow", - "signature": "MAX_TRUSTED_ISSUERS_PER_PAYMENT()", - "type": "MethodAdded" - }, - { - "contract": "Escrow", - "signature": "addDefaultTrustedIssuer(address)", - "type": "MethodAdded" - }, - { - "contract": "Escrow", - "signature": "removeDefaultTrustedIssuer(address,uint256)", - "type": "MethodAdded" - }, - { - "contract": "Escrow", - "signature": "initialize()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Escrow", - "type": "DeployedBytecode" - }, - { - "contract": "Escrow", - "dependency": "Signatures", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "+1", - "minor": "0", - "patch": "0" - } - }, - "Exchange": { - "changes": { - "storage": [], - "major": [ - { - "contract": "Exchange", - "signature": "initialize(address,address,uint256,uint256,uint256,uint256)", - "type": "MethodRemoved" - } - ], - "minor": [ - { - "contract": "Exchange", - "signature": "initialize(address,string,uint256,uint256,uint256,uint256)", - "type": "MethodAdded" - }, - { - "contract": "Exchange", - "signature": "activateStable()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Exchange", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "+1", - "minor": "0", - "patch": "0" - } - }, - "ExchangeBRL": { - "changes": { - "storage": [], - "major": [ - { - "contract": "ExchangeBRL", - "type": "NewContract" - } - ], - "minor": [], - "patch": [] - }, - "versionDelta": { - "storage": "=", - "major": "+2", - "minor": "0", - "patch": "0" - } - }, - "ExchangeEUR": { - "changes": { - "storage": [], - "major": [ - { - "contract": "ExchangeEUR", - "signature": "initialize(address,address,uint256,uint256,uint256,uint256)", - "type": "MethodRemoved" - } - ], - "minor": [ - { - "contract": "ExchangeEUR", - "signature": "initialize(address,string,uint256,uint256,uint256,uint256)", - "type": "MethodAdded" - }, - { - "contract": "ExchangeEUR", - "signature": "activateStable()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "ExchangeEUR", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "+1", - "minor": "0", - "patch": "0" - } - }, - "FederatedAttestations": { - "changes": { - "storage": [], - "major": [ - { - "contract": "FederatedAttestations", - "type": "NewContract" - } - ], - "minor": [], - "patch": [ - { - "contract": "FederatedAttestations", - "dependency": "Signatures", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "+1", - "minor": "0", - "patch": "0" - } - }, - "GrandaMento": { - "changes": { - "storage": [], - "major": [ - { - "contract": "GrandaMento", - "type": "NewContract" - } - ], - "minor": [], - "patch": [] - }, - "versionDelta": { - "storage": "=", - "major": "0", - "minor": "0", - "patch": "+1" - } - }, - "OdisPayments": { - "changes": { - "storage": [], - "major": [ - { - "contract": "OdisPayments", - "type": "NewContract" - } - ], - "minor": [], - "patch": [] - }, - "versionDelta": { - "storage": "=", - "major": "+1", - "minor": "0", - "patch": "0" - } - }, - "StableTokenBRL": { - "changes": { - "storage": [], - "major": [ - { - "contract": "StableTokenBRL", - "type": "NewContract" - } - ], - "minor": [], - "patch": [] - }, - "versionDelta": { - "storage": "=", - "major": "+1", - "minor": "0", - "patch": "+1" - } - }, - "UsingRegistryV2": { - "changes": { - "storage": [], - "major": [ - { - "contract": "UsingRegistryV2", - "type": "NewContract" - } - ], - "minor": [], - "patch": [] - }, - "versionDelta": { - "storage": "=", - "major": "+1", - "minor": "0", - "patch": "0" - } - }, - "Accounts": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "Accounts", - "signature": "setPaymentDelegation(address,uint256)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "getPaymentDelegation(address)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "isSigner(address,address,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "setEip712DomainSeparator()", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "addStorageRoot(bytes)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "removeStorageRoot(uint256)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "getOffchainStorageRoots(address)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "deletePaymentDelegation()", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "setIndexedSigner(address,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "authorizeSignerWithSignature(address,bytes32,uint8,bytes32,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "authorizeSigner(address,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "completeSignerAuthorization(address,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "isLegacySigner(address,address,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "isDefaultSigner(address,address,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "isIndexedSigner(address,address,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "removeDefaultSigner(bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "removeIndexedSigner(bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "removeSigner(address,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "isLegacyRole(bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "getLegacySigner(address,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "getDefaultSigner(address,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "getIndexedSigner(address,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "hasLegacySigner(address,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "hasDefaultSigner(address,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "hasIndexedSigner(address,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "hasAuthorizedSigner(address,string)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "getRoleAuthorizationSigner(address,address,bytes32,uint8,bytes32,bytes32)", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Accounts", - "type": "DeployedBytecode" - }, - { - "contract": "Accounts", - "dependency": "Signatures", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "0" - } - }, - "Election": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "Election", - "signature": "activateForAccount(address,address)", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Election", - "type": "DeployedBytecode" - }, - { - "contract": "Election", - "dependency": "AddressSortedLinkedList", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "+1" - } - }, - "Governance": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "Governance", - "signature": "revokeVotes()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Governance", - "type": "DeployedBytecode" - }, - { - "contract": "Governance", - "dependency": "Proposals", - "type": "LibraryLinkingChange" - }, - { - "contract": "Governance", - "dependency": "IntegerSortedLinkedList", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "-1" - } - }, - "LockedGold": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "LockedGold", - "signature": "getPendingWithdrawal(address,uint256)", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "LockedGold", - "type": "DeployedBytecode" - }, - { - "contract": "LockedGold", - "dependency": "Signatures", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "0" - } - }, - "MetaTransactionWallet": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "MetaTransactionWallet", - "signature": "setGuardian(address)", - "type": "MethodAdded" - }, - { - "contract": "MetaTransactionWallet", - "signature": "recoverWallet(address)", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "MetaTransactionWallet", - "type": "DeployedBytecode" - }, - { - "contract": "MetaTransactionWallet", - "dependency": "Signatures", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "+1" - } - }, - "Attestations": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "Attestations", - "type": "DeployedBytecode" - }, - { - "contract": "Attestations", - "dependency": "Signatures", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - }, - "GoldToken": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "GoldToken", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - }, - "MetaTransactionWalletDeployer": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "MetaTransactionWalletDeployer", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - }, - "Reserve": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "Reserve", - "signature": "getExchangeSpenders()", - "oldValue": "public", - "newValue": "external", - "type": "MethodVisibility" - }, - { - "contract": "Reserve", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+2" - } - }, - "SortedOracles": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "SortedOracles", - "type": "DeployedBytecode" - }, - { - "contract": "SortedOracles", - "dependency": "AddressSortedLinkedListWithMedian", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - }, - "StableToken": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "StableToken", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - }, - "StableTokenEUR": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "StableTokenEUR", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - }, - "Validators": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "Validators", - "type": "DeployedBytecode" - }, - { - "contract": "Validators", - "dependency": "AddressLinkedList", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+3" - } - } - }, - "libraries": { - "AddressLinkedList": { - "storage": [], - "major": [ - { - "contract": "AddressLinkedList", - "signature": "getVersionNumber()", - "type": "MethodRemoved" - } - ], - "minor": [], - "patch": [ - { - "contract": "AddressLinkedList", - "type": "DeployedBytecode" - } - ] - }, - "AddressSortedLinkedList": { - "storage": [], - "major": [ - { - "contract": "AddressSortedLinkedList", - "signature": "getVersionNumber()", - "type": "MethodRemoved" - } - ], - "minor": [], - "patch": [ - { - "contract": "AddressSortedLinkedList", - "type": "DeployedBytecode" - } - ] - }, - "AddressSortedLinkedListWithMedian": { - "storage": [], - "major": [ - { - "contract": "AddressSortedLinkedListWithMedian", - "signature": "getVersionNumber()", - "type": "MethodRemoved" - } - ], - "minor": [], - "patch": [ - { - "contract": "AddressSortedLinkedListWithMedian", - "type": "DeployedBytecode" - } - ] - }, - "IntegerSortedLinkedList": { - "storage": [], - "major": [ - { - "contract": "IntegerSortedLinkedList", - "signature": "getVersionNumber()", - "type": "MethodRemoved" - } - ], - "minor": [], - "patch": [ - { - "contract": "IntegerSortedLinkedList", - "type": "DeployedBytecode" - } - ] - }, - "Proposals": { - "storage": [], - "major": [ - { - "contract": "Proposals", - "signature": "getVersionNumber()", - "type": "MethodRemoved" - } - ], - "minor": [], - "patch": [ - { - "contract": "Proposals", - "type": "DeployedBytecode" - } - ] - }, - "Signatures": { - "storage": [], - "major": [ - { - "contract": "Signatures", - "signature": "getVersionNumber()", - "type": "MethodRemoved" - } - ], - "minor": [], - "patch": [ - { - "contract": "Signatures", - "type": "DeployedBytecode" - } - ] - } - } - } -} diff --git a/packages/protocol/releaseData/versionReports/release1-report.json b/packages/protocol/releaseData/versionReports/release1-report.json deleted file mode 100644 index 4b5a00a32..000000000 --- a/packages/protocol/releaseData/versionReports/release1-report.json +++ /dev/null @@ -1,886 +0,0 @@ -{ - "oldArtifactsFolder": "build/core-contracts.v0/contracts", - "newArtifactsFolder": [ - "build/core-contracts.v1/contracts", - "build/core-contracts.v1/contracts-0.8" - ], - "exclude": "/.*Test|Mock.*|I[A-Z].*|.*Proxy|MultiSig.*|ReleaseGold|SlasherUtil|UsingPrecompiles/", - "report": { - "contracts": { - "DowntimeSlasher": { - "changes": { - "storage": [ - { - "contract": "DowntimeSlasher", - "compatible": false, - "errors": [ - "variable bitmaps was inserted" - ] - } - ], - "major": [ - { - "contract": "DowntimeSlasher", - "signature": "isDown(uint256,uint256,uint256)", - "type": "MethodRemoved" - }, - { - "contract": "DowntimeSlasher", - "signature": "slash(uint256,uint256,uint256,uint256,address[],address[],uint256[],address[],address[],uint256[])", - "type": "MethodRemoved" - } - ], - "minor": [ - { - "contract": "DowntimeSlasher", - "signature": "getVersionNumber()", - "type": "MethodAdded" - }, - { - "contract": "DowntimeSlasher", - "signature": "getBitmapForInterval(uint256,uint256)", - "type": "MethodAdded" - }, - { - "contract": "DowntimeSlasher", - "signature": "setBitmapForInterval(uint256,uint256)", - "type": "MethodAdded" - }, - { - "contract": "DowntimeSlasher", - "signature": "wasDownForInterval(uint256,uint256,uint256)", - "type": "MethodAdded" - }, - { - "contract": "DowntimeSlasher", - "signature": "isBitmapSetForInterval(uint256,uint256)", - "type": "MethodAdded" - }, - { - "contract": "DowntimeSlasher", - "signature": "wasDownForIntervals(uint256[],uint256[],uint256[])", - "type": "MethodAdded" - }, - { - "contract": "DowntimeSlasher", - "signature": "slash(uint256[],uint256[],uint256[],uint256,address[],address[],uint256[],address[],address[],uint256[])", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "DowntimeSlasher", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "+1", - "major": "0", - "minor": "0", - "patch": "0" - } - }, - "Governance": { - "changes": { - "storage": [], - "major": [ - { - "contract": "Governance", - "signature": "getVoteRecord(address,uint256)", - "oldValue": "uint256, uint256", - "newValue": "uint256, uint256, uint256", - "type": "MethodReturn" - } - ], - "minor": [ - { - "contract": "Governance", - "signature": "getVersionNumber()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Governance", - "type": "DeployedBytecode" - }, - { - "contract": "Governance", - "dependency": "Proposals", - "type": "LibraryLinkingChange" - }, - { - "contract": "Governance", - "dependency": "IntegerSortedLinkedList", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "+1", - "minor": "0", - "patch": "0" - } - }, - "MetaTransactionWallet": { - "changes": { - "storage": [], - "major": [ - { - "contract": "MetaTransactionWallet", - "type": "NewContract" - } - ], - "minor": [], - "patch": [ - { - "contract": "MetaTransactionWallet", - "dependency": "Signatures", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "+1", - "minor": "0", - "patch": "0" - } - }, - "Accounts": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "Accounts", - "signature": "getVersionNumber()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Accounts", - "type": "DeployedBytecode" - }, - { - "contract": "Accounts", - "dependency": "Signatures", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "0" - } - }, - "Attestations": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "Attestations", - "signature": "approveTransfer(bytes32,uint256,address,address,bool)", - "type": "MethodAdded" - }, - { - "contract": "Attestations", - "signature": "requireNAttestationsRequested(bytes32,address,uint32)", - "type": "MethodAdded" - }, - { - "contract": "Attestations", - "signature": "getVersionNumber()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Attestations", - "type": "DeployedBytecode" - }, - { - "contract": "Attestations", - "dependency": "Signatures", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "0" - } - }, - "DoubleSigningSlasher": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "DoubleSigningSlasher", - "signature": "getVersionNumber()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "DoubleSigningSlasher", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "0" - } - }, - "Election": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "Election", - "signature": "getVersionNumber()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Election", - "signature": "revokeActive(address,uint256,address,address,uint256)", - "oldValue": "public", - "newValue": "external", - "type": "MethodVisibility" - }, - { - "contract": "Election", - "type": "DeployedBytecode" - }, - { - "contract": "Election", - "dependency": "AddressSortedLinkedList", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "0" - } - }, - "EpochRewards": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "EpochRewards", - "signature": "getVersionNumber()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "EpochRewards", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "0" - } - }, - "Escrow": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "Escrow", - "signature": "getVersionNumber()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Escrow", - "type": "DeployedBytecode" - }, - { - "contract": "Escrow", - "dependency": "Signatures", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "0" - } - }, - "Exchange": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "Exchange", - "signature": "buy(uint256,uint256,bool)", - "type": "MethodAdded" - }, - { - "contract": "Exchange", - "signature": "sell(uint256,uint256,bool)", - "type": "MethodAdded" - }, - { - "contract": "Exchange", - "signature": "getVersionNumber()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Exchange", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "0" - } - }, - "GasPriceMinimum": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "GasPriceMinimum", - "signature": "getVersionNumber()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "GasPriceMinimum", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "0" - } - }, - "GoldToken": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "GoldToken", - "signature": "getVersionNumber()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "GoldToken", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "0" - } - }, - "LockedGold": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "LockedGold", - "signature": "getVersionNumber()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "LockedGold", - "type": "DeployedBytecode" - }, - { - "contract": "LockedGold", - "dependency": "Signatures", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "0" - } - }, - "Random": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "Random", - "signature": "getVersionNumber()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Random", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "0" - } - }, - "Reserve": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "Reserve", - "signature": "getVersionNumber()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Reserve", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "0" - } - }, - "SortedOracles": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "SortedOracles", - "signature": "getVersionNumber()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "SortedOracles", - "type": "DeployedBytecode" - }, - { - "contract": "SortedOracles", - "dependency": "AddressSortedLinkedListWithMedian", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "0" - } - }, - "StableToken": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "StableToken", - "signature": "getVersionNumber()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "StableToken", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "0" - } - }, - "Validators": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "Validators", - "signature": "getVersionNumber()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Validators", - "type": "DeployedBytecode" - }, - { - "contract": "Validators", - "dependency": "AddressLinkedList", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "0" - } - } - }, - "libraries": { - "LinkedList": { - "storage": [], - "major": [ - { - "contract": "LinkedList", - "signature": "insert(struct LinkedList.List,bytes32,bytes32,bytes32)", - "type": "MethodRemoved" - }, - { - "contract": "LinkedList", - "signature": "push(struct LinkedList.List,bytes32)", - "type": "MethodRemoved" - }, - { - "contract": "LinkedList", - "signature": "remove(struct LinkedList.List,bytes32)", - "type": "MethodRemoved" - }, - { - "contract": "LinkedList", - "signature": "update(struct LinkedList.List,bytes32,bytes32,bytes32)", - "type": "MethodRemoved" - }, - { - "contract": "LinkedList", - "signature": "contains(struct LinkedList.List,bytes32)", - "type": "MethodRemoved" - }, - { - "contract": "LinkedList", - "signature": "headN(struct LinkedList.List,uint256)", - "type": "MethodRemoved" - }, - { - "contract": "LinkedList", - "signature": "getKeys(struct LinkedList.List)", - "type": "MethodRemoved" - } - ], - "minor": [], - "patch": [ - { - "contract": "LinkedList", - "type": "DeployedBytecode" - } - ] - }, - "SortedLinkedList": { - "storage": [], - "major": [ - { - "contract": "SortedLinkedList", - "signature": "insert(struct SortedLinkedList.List,bytes32,uint256,bytes32,bytes32)", - "type": "MethodRemoved" - }, - { - "contract": "SortedLinkedList", - "signature": "remove(struct SortedLinkedList.List,bytes32)", - "type": "MethodRemoved" - }, - { - "contract": "SortedLinkedList", - "signature": "update(struct SortedLinkedList.List,bytes32,uint256,bytes32,bytes32)", - "type": "MethodRemoved" - }, - { - "contract": "SortedLinkedList", - "signature": "push(struct SortedLinkedList.List,bytes32)", - "type": "MethodRemoved" - }, - { - "contract": "SortedLinkedList", - "signature": "popN(struct SortedLinkedList.List,uint256)", - "type": "MethodRemoved" - }, - { - "contract": "SortedLinkedList", - "signature": "contains(struct SortedLinkedList.List,bytes32)", - "type": "MethodRemoved" - }, - { - "contract": "SortedLinkedList", - "signature": "getValue(struct SortedLinkedList.List,bytes32)", - "type": "MethodRemoved" - }, - { - "contract": "SortedLinkedList", - "signature": "getElements(struct SortedLinkedList.List)", - "type": "MethodRemoved" - }, - { - "contract": "SortedLinkedList", - "signature": "getKeys(struct SortedLinkedList.List)", - "type": "MethodRemoved" - }, - { - "contract": "SortedLinkedList", - "signature": "headN(struct SortedLinkedList.List,uint256)", - "type": "MethodRemoved" - } - ], - "minor": [], - "patch": [ - { - "contract": "SortedLinkedList", - "type": "DeployedBytecode" - } - ] - }, - "SortedLinkedListWithMedian": { - "storage": [], - "major": [ - { - "contract": "SortedLinkedListWithMedian", - "signature": "insert(struct SortedLinkedListWithMedian.List,bytes32,uint256,bytes32,bytes32)", - "type": "MethodRemoved" - }, - { - "contract": "SortedLinkedListWithMedian", - "signature": "remove(struct SortedLinkedListWithMedian.List,bytes32)", - "type": "MethodRemoved" - }, - { - "contract": "SortedLinkedListWithMedian", - "signature": "update(struct SortedLinkedListWithMedian.List,bytes32,uint256,bytes32,bytes32)", - "type": "MethodRemoved" - }, - { - "contract": "SortedLinkedListWithMedian", - "signature": "push(struct SortedLinkedListWithMedian.List,bytes32)", - "type": "MethodRemoved" - }, - { - "contract": "SortedLinkedListWithMedian", - "signature": "popN(struct SortedLinkedListWithMedian.List,uint256)", - "type": "MethodRemoved" - }, - { - "contract": "SortedLinkedListWithMedian", - "signature": "contains(struct SortedLinkedListWithMedian.List,bytes32)", - "type": "MethodRemoved" - }, - { - "contract": "SortedLinkedListWithMedian", - "signature": "getValue(struct SortedLinkedListWithMedian.List,bytes32)", - "type": "MethodRemoved" - }, - { - "contract": "SortedLinkedListWithMedian", - "signature": "getMedianValue(struct SortedLinkedListWithMedian.List)", - "type": "MethodRemoved" - }, - { - "contract": "SortedLinkedListWithMedian", - "signature": "getHead(struct SortedLinkedListWithMedian.List)", - "type": "MethodRemoved" - }, - { - "contract": "SortedLinkedListWithMedian", - "signature": "getMedian(struct SortedLinkedListWithMedian.List)", - "type": "MethodRemoved" - }, - { - "contract": "SortedLinkedListWithMedian", - "signature": "getTail(struct SortedLinkedListWithMedian.List)", - "type": "MethodRemoved" - }, - { - "contract": "SortedLinkedListWithMedian", - "signature": "getNumElements(struct SortedLinkedListWithMedian.List)", - "type": "MethodRemoved" - }, - { - "contract": "SortedLinkedListWithMedian", - "signature": "getElements(struct SortedLinkedListWithMedian.List)", - "type": "MethodRemoved" - }, - { - "contract": "SortedLinkedListWithMedian", - "signature": "getKeys(struct SortedLinkedListWithMedian.List)", - "type": "MethodRemoved" - } - ], - "minor": [], - "patch": [ - { - "contract": "SortedLinkedListWithMedian", - "type": "DeployedBytecode" - } - ] - }, - "AddressLinkedList": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "AddressLinkedList", - "signature": "getVersionNumber()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "AddressLinkedList", - "type": "DeployedBytecode" - } - ] - }, - "AddressSortedLinkedList": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "AddressSortedLinkedList", - "signature": "getVersionNumber()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "AddressSortedLinkedList", - "type": "DeployedBytecode" - } - ] - }, - "AddressSortedLinkedListWithMedian": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "AddressSortedLinkedListWithMedian", - "signature": "getVersionNumber()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "AddressSortedLinkedListWithMedian", - "type": "DeployedBytecode" - } - ] - }, - "IntegerSortedLinkedList": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "IntegerSortedLinkedList", - "signature": "getVersionNumber()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "IntegerSortedLinkedList", - "type": "DeployedBytecode" - } - ] - }, - "Proposals": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "Proposals", - "signature": "getVersionNumber()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Proposals", - "type": "DeployedBytecode" - } - ] - }, - "Signatures": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "Signatures", - "signature": "getVersionNumber()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Signatures", - "type": "DeployedBytecode" - } - ] - } - } - } -} diff --git a/packages/protocol/releaseData/versionReports/release2-report.json b/packages/protocol/releaseData/versionReports/release2-report.json deleted file mode 100644 index 5030b9cfb..000000000 --- a/packages/protocol/releaseData/versionReports/release2-report.json +++ /dev/null @@ -1,245 +0,0 @@ -{ - "oldArtifactsFolder": "build/core-contracts.v1/contracts", - "newArtifactsFolder": [ - "build/core-contracts.v2/contracts", - "build/core-contracts.v2/contracts-0.8" - ], - "exclude": "/.*Test|Mock.*|I[A-Z].*|.*Proxy|MultiSig.*|ReleaseGold|SlasherUtil|UsingPrecompiles/", - "report": { - "contracts": { - "MetaTransactionWalletDeployer": { - "changes": { - "storage": [], - "major": [ - { - "contract": "MetaTransactionWalletDeployer", - "type": "NewContract" - } - ], - "minor": [], - "patch": [] - }, - "versionDelta": { - "storage": "=", - "major": "+1", - "minor": "0", - "patch": "0" - } - }, - "SortedOracles": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "SortedOracles", - "signature": "setTokenReportExpiry(address,uint256)", - "type": "MethodAdded" - }, - { - "contract": "SortedOracles", - "signature": "getTokenReportExpirySeconds(address)", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "SortedOracles", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "0" - } - }, - "Accounts": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "Accounts", - "type": "DeployedBytecode" - }, - { - "contract": "Accounts", - "dependency": "Signatures", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - }, - "Attestations": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "Attestations", - "type": "DeployedBytecode" - }, - { - "contract": "Attestations", - "dependency": "Signatures", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - }, - "Escrow": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "Escrow", - "type": "DeployedBytecode" - }, - { - "contract": "Escrow", - "dependency": "Signatures", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - }, - "Governance": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "Governance", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - }, - "LockedGold": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "LockedGold", - "type": "DeployedBytecode" - }, - { - "contract": "LockedGold", - "dependency": "Signatures", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - }, - "MetaTransactionWallet": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "MetaTransactionWallet", - "signature": "getMetaTransactionDigest(address,uint256,bytes,uint256)", - "oldValue": "public", - "newValue": "external", - "type": "MethodVisibility" - }, - { - "contract": "MetaTransactionWallet", - "signature": "setSigner(address)", - "oldValue": "public", - "newValue": "external", - "type": "MethodVisibility" - }, - { - "contract": "MetaTransactionWallet", - "signature": "getVersionNumber()", - "oldValue": "public", - "newValue": "external", - "type": "MethodVisibility" - }, - { - "contract": "MetaTransactionWallet", - "type": "DeployedBytecode" - }, - { - "contract": "MetaTransactionWallet", - "dependency": "Signatures", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - } - }, - "libraries": { - "Signatures": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "Signatures", - "signature": "toEthSignedTypedDataHash(bytes32,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Signatures", - "signature": "getSignerOfTypedDataHash(bytes32,bytes32,uint8,bytes32,bytes32)", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Signatures", - "type": "DeployedBytecode" - } - ] - } - } - } -} diff --git a/packages/protocol/releaseData/versionReports/release3-report.json b/packages/protocol/releaseData/versionReports/release3-report.json deleted file mode 100644 index cac02545a..000000000 --- a/packages/protocol/releaseData/versionReports/release3-report.json +++ /dev/null @@ -1,298 +0,0 @@ -{ - "oldArtifactsFolder": "build/core-contracts.v2/contracts", - "newArtifactsFolder": [ - "build/core-contracts.v3/contracts", - "build/core-contracts.v3/contracts-0.8" - ], - "exclude": "/.*Test|Mock.*|I[A-Z].*|.*Proxy|MultiSig.*|ReleaseGold|SlasherUtil|UsingPrecompiles/", - "report": { - "contracts": { - "BlockchainParameters": { - "changes": { - "storage": [], - "major": [ - { - "contract": "BlockchainParameters", - "signature": "initialize(uint256,uint256,uint256,uint256,uint256)", - "type": "MethodRemoved" - } - ], - "minor": [ - { - "contract": "BlockchainParameters", - "signature": "fractionMulExp(uint256,uint256,uint256,uint256,uint256,uint256)", - "type": "MethodAdded" - }, - { - "contract": "BlockchainParameters", - "signature": "getEpochSize()", - "type": "MethodAdded" - }, - { - "contract": "BlockchainParameters", - "signature": "getEpochNumberOfBlock(uint256)", - "type": "MethodAdded" - }, - { - "contract": "BlockchainParameters", - "signature": "getEpochNumber()", - "type": "MethodAdded" - }, - { - "contract": "BlockchainParameters", - "signature": "validatorSignerAddressFromCurrentSet(uint256)", - "type": "MethodAdded" - }, - { - "contract": "BlockchainParameters", - "signature": "validatorSignerAddressFromSet(uint256,uint256)", - "type": "MethodAdded" - }, - { - "contract": "BlockchainParameters", - "signature": "numberValidatorsInCurrentSet()", - "type": "MethodAdded" - }, - { - "contract": "BlockchainParameters", - "signature": "numberValidatorsInSet(uint256)", - "type": "MethodAdded" - }, - { - "contract": "BlockchainParameters", - "signature": "checkProofOfPossession(address,bytes,bytes)", - "type": "MethodAdded" - }, - { - "contract": "BlockchainParameters", - "signature": "getBlockNumberFromHeader(bytes)", - "type": "MethodAdded" - }, - { - "contract": "BlockchainParameters", - "signature": "hashHeader(bytes)", - "type": "MethodAdded" - }, - { - "contract": "BlockchainParameters", - "signature": "getParentSealBitmap(uint256)", - "type": "MethodAdded" - }, - { - "contract": "BlockchainParameters", - "signature": "getVerifiedSealBitmapFromHeader(bytes)", - "type": "MethodAdded" - }, - { - "contract": "BlockchainParameters", - "signature": "minQuorumSize(uint256)", - "type": "MethodAdded" - }, - { - "contract": "BlockchainParameters", - "signature": "minQuorumSizeInCurrentSet()", - "type": "MethodAdded" - }, - { - "contract": "BlockchainParameters", - "signature": "initialize(uint256,uint256,uint256,uint256,uint256,uint256)", - "type": "MethodAdded" - }, - { - "contract": "BlockchainParameters", - "signature": "getVersionNumber()", - "type": "MethodAdded" - }, - { - "contract": "BlockchainParameters", - "signature": "setUptimeLookbackWindow(uint256)", - "type": "MethodAdded" - }, - { - "contract": "BlockchainParameters", - "signature": "getUptimeLookbackWindow()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "BlockchainParameters", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "+1", - "minor": "0", - "patch": "0" - } - }, - "ExchangeEUR": { - "changes": { - "storage": [], - "major": [ - { - "contract": "ExchangeEUR", - "type": "NewContract" - } - ], - "minor": [], - "patch": [] - }, - "versionDelta": { - "storage": "=", - "major": "+1", - "minor": "0", - "patch": "0" - } - }, - "StableToken": { - "changes": { - "storage": [], - "major": [ - { - "contract": "StableToken", - "signature": "initialize(string,string,uint8,address,uint256,uint256,address[],uint256[])", - "type": "MethodRemoved" - } - ], - "minor": [ - { - "contract": "StableToken", - "signature": "initialize(string,string,uint8,address,uint256,uint256,address[],uint256[],string)", - "type": "MethodAdded" - }, - { - "contract": "StableToken", - "signature": "getExchangeRegistryId()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "StableToken", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "+1", - "minor": "0", - "patch": "0" - } - }, - "StableTokenEUR": { - "changes": { - "storage": [], - "major": [ - { - "contract": "StableTokenEUR", - "type": "NewContract" - } - ], - "minor": [], - "patch": [] - }, - "versionDelta": { - "storage": "=", - "major": "+1", - "minor": "0", - "patch": "0" - } - }, - "Validators": { - "changes": { - "storage": [], - "major": [ - { - "contract": "Validators", - "signature": "initialize(address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)", - "type": "MethodRemoved" - } - ], - "minor": [ - { - "contract": "Validators", - "signature": "initialize(address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)", - "type": "MethodAdded" - }, - { - "contract": "Validators", - "signature": "setDowntimeGracePeriod(uint256)", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Validators", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "+1", - "minor": "0", - "patch": "0" - } - }, - "Reserve": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "Reserve", - "signature": "addExchangeSpender(address)", - "type": "MethodAdded" - }, - { - "contract": "Reserve", - "signature": "removeExchangeSpender(address,uint256)", - "type": "MethodAdded" - }, - { - "contract": "Reserve", - "signature": "getExchangeSpenders()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Reserve", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "0" - } - }, - "Governance": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "Governance", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - } - }, - "libraries": {} - } -} diff --git a/packages/protocol/releaseData/versionReports/release4-report.json b/packages/protocol/releaseData/versionReports/release4-report.json deleted file mode 100644 index 0797607a6..000000000 --- a/packages/protocol/releaseData/versionReports/release4-report.json +++ /dev/null @@ -1,282 +0,0 @@ -{ - "oldArtifactsFolder": "build/core-contracts.v3/contracts", - "newArtifactsFolder": [ - "build/core-contracts.v4/contracts", - "build/core-contracts.v4/contracts-0.8" - ], - "exclude": "/.*Test|Mock.*|I[A-Z].*|.*Proxy|MultiSig.*|ReleaseGold|SlasherUtil|UsingPrecompiles/", - "report": { - "contracts": { - "Accounts": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "Accounts", - "signature": "setEip712DomainSeparator()", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "setIndexedSigner(address,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "authorizeSignerWithSignature(address,bytes32,uint8,bytes32,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "authorizeSigner(address,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "completeSignerAuthorization(address,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "isLegacySigner(address,address,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "isDefaultSigner(address,address,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "isIndexedSigner(address,address,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "isSigner(address,address,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "removeDefaultSigner(bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "removeIndexedSigner(bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "removeSigner(address,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "isLegacyRole(bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "getLegacySigner(address,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "getDefaultSigner(address,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "getIndexedSigner(address,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "hasLegacySigner(address,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "hasDefaultSigner(address,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "hasIndexedSigner(address,bytes32)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "hasAuthorizedSigner(address,string)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "getRoleAuthorizationSigner(address,address,bytes32,uint8,bytes32,bytes32)", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Accounts", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "0" - } - }, - "Election": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "Election", - "signature": "activateForAccount(address,address)", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Election", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "0" - } - }, - "Governance": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "Governance", - "signature": "revokeVotes()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Governance", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "0" - } - }, - "MetaTransactionWallet": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "MetaTransactionWallet", - "signature": "setGuardian(address)", - "type": "MethodAdded" - }, - { - "contract": "MetaTransactionWallet", - "signature": "recoverWallet(address)", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "MetaTransactionWallet", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "0" - } - }, - "GoldToken": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "GoldToken", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - }, - "MetaTransactionWalletDeployer": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "MetaTransactionWalletDeployer", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - }, - "Reserve": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "Reserve", - "signature": "getExchangeSpenders()", - "oldValue": "public", - "newValue": "external", - "type": "MethodVisibility" - }, - { - "contract": "Reserve", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - } - }, - "libraries": {} - } -} diff --git a/packages/protocol/releaseData/versionReports/release5-report.json b/packages/protocol/releaseData/versionReports/release5-report.json deleted file mode 100644 index e62c02849..000000000 --- a/packages/protocol/releaseData/versionReports/release5-report.json +++ /dev/null @@ -1,108 +0,0 @@ -{ - "oldArtifactsFolder": "build/core-contracts.v4/contracts", - "newArtifactsFolder": [ - "build/core-contracts.v5/contracts", - "build/core-contracts.v5/contracts-0.8" - ], - "exclude": "/.*Test|Mock.*|I[A-Z].*|.*Proxy|MultiSig.*|ReleaseGold|SlasherUtil|UsingPrecompiles/", - "report": { - "contracts": { - "GrandaMento": { - "changes": { - "storage": [], - "major": [ - { - "contract": "GrandaMento", - "type": "NewContract" - } - ], - "minor": [], - "patch": [] - }, - "versionDelta": { - "storage": "=", - "major": "+1", - "minor": "0", - "patch": "0" - } - }, - "UsingRegistryV2": { - "changes": { - "storage": [], - "major": [ - { - "contract": "UsingRegistryV2", - "type": "NewContract" - } - ], - "minor": [], - "patch": [] - }, - "versionDelta": { - "storage": "=", - "major": "+1", - "minor": "0", - "patch": "0" - } - }, - "StableToken": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "StableToken", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - }, - "StableTokenEUR": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "StableTokenEUR", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - }, - "Validators": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "Validators", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - } - }, - "libraries": {} - } -} diff --git a/packages/protocol/releaseData/versionReports/release6-report.json b/packages/protocol/releaseData/versionReports/release6-report.json deleted file mode 100644 index 0c2d8ef95..000000000 --- a/packages/protocol/releaseData/versionReports/release6-report.json +++ /dev/null @@ -1,391 +0,0 @@ -{ - "oldArtifactsFolder": "build/core-contracts.v5/contracts", - "newArtifactsFolder": [ - "build/core-contracts.v6/contracts", - "build/core-contracts.v6/contracts-0.8" - ], - "exclude": "/.*Test|Mock.*|I[A-Z].*|.*Proxy|MultiSig.*|ReleaseGold|SlasherUtil|UsingPrecompiles/", - "report": { - "contracts": { - "ExchangeBRL": { - "changes": { - "storage": [], - "major": [ - { - "contract": "ExchangeBRL", - "type": "NewContract" - } - ], - "minor": [], - "patch": [] - }, - "versionDelta": { - "storage": "=", - "major": "+1", - "minor": "0", - "patch": "0" - } - }, - "StableTokenBRL": { - "changes": { - "storage": [], - "major": [ - { - "contract": "StableTokenBRL", - "type": "NewContract" - } - ], - "minor": [], - "patch": [] - }, - "versionDelta": { - "storage": "=", - "major": "+1", - "minor": "0", - "patch": "0" - } - }, - "Accounts": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "Accounts", - "signature": "addStorageRoot(bytes)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "removeStorageRoot(uint256)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "getOffchainStorageRoots(address)", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Accounts", - "type": "DeployedBytecode" - }, - { - "contract": "Accounts", - "dependency": "Signatures", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "0" - } - }, - "Attestations": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "Attestations", - "type": "DeployedBytecode" - }, - { - "contract": "Attestations", - "dependency": "Signatures", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - }, - "Election": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "Election", - "type": "DeployedBytecode" - }, - { - "contract": "Election", - "dependency": "AddressSortedLinkedList", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - }, - "Escrow": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "Escrow", - "type": "DeployedBytecode" - }, - { - "contract": "Escrow", - "dependency": "Signatures", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - }, - "Governance": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "Governance", - "type": "DeployedBytecode" - }, - { - "contract": "Governance", - "dependency": "Proposals", - "type": "LibraryLinkingChange" - }, - { - "contract": "Governance", - "dependency": "IntegerSortedLinkedList", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - }, - "LockedGold": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "LockedGold", - "type": "DeployedBytecode" - }, - { - "contract": "LockedGold", - "dependency": "Signatures", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - }, - "MetaTransactionWallet": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "MetaTransactionWallet", - "type": "DeployedBytecode" - }, - { - "contract": "MetaTransactionWallet", - "dependency": "Signatures", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - }, - "SortedOracles": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "SortedOracles", - "type": "DeployedBytecode" - }, - { - "contract": "SortedOracles", - "dependency": "AddressSortedLinkedListWithMedian", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - }, - "Validators": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "Validators", - "type": "DeployedBytecode" - }, - { - "contract": "Validators", - "dependency": "AddressLinkedList", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - } - }, - "libraries": { - "AddressLinkedList": { - "storage": [], - "major": [ - { - "contract": "AddressLinkedList", - "signature": "getVersionNumber()", - "type": "MethodRemoved" - } - ], - "minor": [], - "patch": [ - { - "contract": "AddressLinkedList", - "type": "DeployedBytecode" - } - ] - }, - "AddressSortedLinkedList": { - "storage": [], - "major": [ - { - "contract": "AddressSortedLinkedList", - "signature": "getVersionNumber()", - "type": "MethodRemoved" - } - ], - "minor": [], - "patch": [ - { - "contract": "AddressSortedLinkedList", - "type": "DeployedBytecode" - } - ] - }, - "AddressSortedLinkedListWithMedian": { - "storage": [], - "major": [ - { - "contract": "AddressSortedLinkedListWithMedian", - "signature": "getVersionNumber()", - "type": "MethodRemoved" - } - ], - "minor": [], - "patch": [ - { - "contract": "AddressSortedLinkedListWithMedian", - "type": "DeployedBytecode" - } - ] - }, - "IntegerSortedLinkedList": { - "storage": [], - "major": [ - { - "contract": "IntegerSortedLinkedList", - "signature": "getVersionNumber()", - "type": "MethodRemoved" - } - ], - "minor": [], - "patch": [ - { - "contract": "IntegerSortedLinkedList", - "type": "DeployedBytecode" - } - ] - }, - "Proposals": { - "storage": [], - "major": [ - { - "contract": "Proposals", - "signature": "getVersionNumber()", - "type": "MethodRemoved" - } - ], - "minor": [], - "patch": [ - { - "contract": "Proposals", - "type": "DeployedBytecode" - } - ] - }, - "Signatures": { - "storage": [], - "major": [ - { - "contract": "Signatures", - "signature": "getVersionNumber()", - "type": "MethodRemoved" - } - ], - "minor": [], - "patch": [ - { - "contract": "Signatures", - "type": "DeployedBytecode" - } - ] - } - } - } -} diff --git a/packages/protocol/releaseData/versionReports/release7-report.json b/packages/protocol/releaseData/versionReports/release7-report.json deleted file mode 100644 index e9f9b13d9..000000000 --- a/packages/protocol/releaseData/versionReports/release7-report.json +++ /dev/null @@ -1,238 +0,0 @@ -{ - "oldArtifactsFolder": "build/core-contracts.v6/contracts", - "newArtifactsFolder": [ - "build/core-contracts.v7/contracts", - "build/core-contracts.v7/contracts-0.8" - ], - "exclude": "/.*Test|Mock.*|I[A-Z].*|.*Proxy|MultiSig.*|ReleaseGold|SlasherUtil|UsingPrecompiles/", - "report": { - "contracts": { - "Exchange": { - "changes": { - "storage": [], - "major": [ - { - "contract": "Exchange", - "signature": "initialize(address,address,uint256,uint256,uint256,uint256)", - "type": "MethodRemoved" - } - ], - "minor": [ - { - "contract": "Exchange", - "signature": "initialize(address,string,uint256,uint256,uint256,uint256)", - "type": "MethodAdded" - }, - { - "contract": "Exchange", - "signature": "activateStable()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Exchange", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "+1", - "minor": "0", - "patch": "0" - } - }, - "ExchangeBRL": { - "changes": { - "storage": [], - "major": [ - { - "contract": "ExchangeBRL", - "signature": "initialize(address,address,uint256,uint256,uint256,uint256)", - "type": "MethodRemoved" - } - ], - "minor": [ - { - "contract": "ExchangeBRL", - "signature": "initialize(address,string,uint256,uint256,uint256,uint256)", - "type": "MethodAdded" - }, - { - "contract": "ExchangeBRL", - "signature": "activateStable()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "ExchangeBRL", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "+1", - "minor": "0", - "patch": "0" - } - }, - "ExchangeEUR": { - "changes": { - "storage": [], - "major": [ - { - "contract": "ExchangeEUR", - "signature": "initialize(address,address,uint256,uint256,uint256,uint256)", - "type": "MethodRemoved" - } - ], - "minor": [ - { - "contract": "ExchangeEUR", - "signature": "initialize(address,string,uint256,uint256,uint256,uint256)", - "type": "MethodAdded" - }, - { - "contract": "ExchangeEUR", - "signature": "activateStable()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "ExchangeEUR", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "+1", - "minor": "0", - "patch": "0" - } - }, - "Accounts": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "Accounts", - "signature": "setPaymentDelegation(address,uint256)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "getPaymentDelegation(address)", - "type": "MethodAdded" - }, - { - "contract": "Accounts", - "signature": "deletePaymentDelegation()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Accounts", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "0" - } - }, - "LockedGold": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "LockedGold", - "signature": "getPendingWithdrawal(address,uint256)", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "LockedGold", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "0" - } - }, - "GrandaMento": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "GrandaMento", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - }, - "Reserve": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "Reserve", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - }, - "Validators": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "Validators", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - } - }, - "libraries": {} - } -} diff --git a/packages/protocol/releaseData/versionReports/release8-report.json b/packages/protocol/releaseData/versionReports/release8-report.json deleted file mode 100644 index fb6e66649..000000000 --- a/packages/protocol/releaseData/versionReports/release8-report.json +++ /dev/null @@ -1,117 +0,0 @@ -{ - "oldArtifactsFolder": "build/core-contracts.v7/contracts", - "newArtifactsFolder": [ - "build/core-contracts.v8/contracts", - "build/core-contracts.v8/contracts-0.8" - ], - "exclude": "/.*Test|Mock.*|I[A-Z].*|.*Proxy|MultiSig.*|ReleaseGold|SlasherUtil|UsingPrecompiles|^UsingRegistry/", - "report": { - "contracts": { - "Escrow": { - "changes": { - "storage": [], - "major": [ - { - "contract": "Escrow", - "signature": "setRegistry(address)", - "type": "MethodRemoved" - }, - { - "contract": "Escrow", - "signature": "initialize(address)", - "type": "MethodRemoved" - } - ], - "minor": [ - { - "contract": "Escrow", - "signature": "transferWithTrustedIssuers(bytes32,address,uint256,uint256,address,uint256,address[])", - "type": "MethodAdded" - }, - { - "contract": "Escrow", - "signature": "getTrustedIssuersPerPayment(address)", - "type": "MethodAdded" - }, - { - "contract": "Escrow", - "signature": "getDefaultTrustedIssuers()", - "type": "MethodAdded" - }, - { - "contract": "Escrow", - "signature": "MAX_TRUSTED_ISSUERS_PER_PAYMENT()", - "type": "MethodAdded" - }, - { - "contract": "Escrow", - "signature": "addDefaultTrustedIssuer(address)", - "type": "MethodAdded" - }, - { - "contract": "Escrow", - "signature": "removeDefaultTrustedIssuer(address,uint256)", - "type": "MethodAdded" - }, - { - "contract": "Escrow", - "signature": "initialize()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Escrow", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "+1", - "minor": "0", - "patch": "0" - } - }, - "FederatedAttestations": { - "changes": { - "storage": [], - "major": [ - { - "contract": "FederatedAttestations", - "type": "NewContract" - } - ], - "minor": [], - "patch": [] - }, - "versionDelta": { - "storage": "=", - "major": "+1", - "minor": "0", - "patch": "0" - } - }, - "OdisPayments": { - "changes": { - "storage": [], - "major": [ - { - "contract": "OdisPayments", - "type": "NewContract" - } - ], - "minor": [], - "patch": [] - }, - "versionDelta": { - "storage": "=", - "major": "+1", - "minor": "0", - "patch": "0" - } - } - }, - "libraries": {} - } -} diff --git a/packages/protocol/releaseData/versionReports/release9-report.json b/packages/protocol/releaseData/versionReports/release9-report.json deleted file mode 100644 index 0423d4812..000000000 --- a/packages/protocol/releaseData/versionReports/release9-report.json +++ /dev/null @@ -1,267 +0,0 @@ -{ - "oldArtifactsFolder": "build/core-contracts.v8/contracts", - "newArtifactsFolder": [ - "build/core-contracts.v9/contracts", - "build/core-contracts.v9/contracts-0.8" - ], - "exclude": "/.*Test|Mock.*|I[A-Z].*|.*Proxy|MultiSig.*|ReleaseGold|SlasherUtil|UsingPrecompiles|^UsingRegistry/", - "report": { - "contracts": { - "Attestations": { - "changes": { - "storage": [], - "major": [ - { - "contract": "Attestations", - "signature": "request(bytes32,uint256,address)", - "type": "MethodRemoved" - }, - { - "contract": "Attestations", - "signature": "selectIssuers(bytes32)", - "type": "MethodRemoved" - }, - { - "contract": "Attestations", - "signature": "complete(bytes32,uint8,bytes32,bytes32)", - "type": "MethodRemoved" - }, - { - "contract": "Attestations", - "signature": "approveTransfer(bytes32,uint256,address,address,bool)", - "type": "MethodRemoved" - } - ], - "minor": [], - "patch": [ - { - "contract": "Attestations", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "+1", - "minor": "0", - "patch": "0" - } - }, - "Governance": { - "changes": { - "storage": [], - "major": [ - { - "contract": "Governance", - "signature": "initialize(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)", - "type": "MethodRemoved" - }, - { - "contract": "Governance", - "signature": "setApprovalStageDuration(uint256)", - "type": "MethodRemoved" - }, - { - "contract": "Governance", - "signature": "getApprovalStageDuration()", - "type": "MethodRemoved" - }, - { - "contract": "Governance", - "signature": "getVoteRecord(address,uint256)", - "oldValue": "uint256, uint256, uint256", - "newValue": "uint256, uint256, uint256, uint256, uint256, uint256", - "type": "MethodReturn" - } - ], - "minor": [ - { - "contract": "Governance", - "signature": "getAmountOfGoldUsedForVoting(address)", - "type": "MethodAdded" - }, - { - "contract": "Governance", - "signature": "initialize(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)", - "type": "MethodAdded" - }, - { - "contract": "Governance", - "signature": "votePartially(uint256,uint256,uint256,uint256,uint256)", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Governance", - "type": "DeployedBytecode" - }, - { - "contract": "Governance", - "dependency": "Proposals", - "type": "LibraryLinkingChange" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "+1", - "minor": "0", - "patch": "0" - } - }, - "Election": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "Election", - "signature": "allowedToVoteOverMaxNumberOfGroups(address)", - "type": "MethodAdded" - }, - { - "contract": "Election", - "signature": "updateTotalVotesByAccountForGroup(address,address)", - "type": "MethodAdded" - }, - { - "contract": "Election", - "signature": "setAllowedToVoteOverMaxNumberOfGroups(bool)", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Election", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "0" - } - }, - "GoldToken": { - "changes": { - "storage": [], - "major": [], - "minor": [ - { - "contract": "GoldToken", - "signature": "burn(uint256)", - "type": "MethodAdded" - }, - { - "contract": "GoldToken", - "signature": "circulatingSupply()", - "type": "MethodAdded" - }, - { - "contract": "GoldToken", - "signature": "getBurnedAmount()", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "GoldToken", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "+1", - "patch": "0" - } - }, - "LockedGold": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "LockedGold", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - }, - "MetaTransactionWalletDeployer": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "MetaTransactionWalletDeployer", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - }, - "Validators": { - "changes": { - "storage": [], - "major": [], - "minor": [], - "patch": [ - { - "contract": "Validators", - "type": "DeployedBytecode" - } - ] - }, - "versionDelta": { - "storage": "=", - "major": "=", - "minor": "=", - "patch": "+1" - } - } - }, - "libraries": { - "Proposals": { - "storage": [], - "major": [ - { - "contract": "Proposals", - "signature": "updateVote(struct Proposals.Proposal,uint256,uint256,enum Proposals.VoteValue,enum Proposals.VoteValue)", - "type": "MethodRemoved" - } - ], - "minor": [ - { - "contract": "Proposals", - "signature": "updateVote(struct Proposals.Proposal,uint256,uint256,uint256,uint256,uint256,uint256)", - "type": "MethodAdded" - } - ], - "patch": [ - { - "contract": "Proposals", - "type": "DeployedBytecode" - } - ] - } - } - } -} diff --git a/packages/protocol/remappings.txt b/packages/protocol/remappings.txt deleted file mode 100644 index ade04c498..000000000 --- a/packages/protocol/remappings.txt +++ /dev/null @@ -1,3 +0,0 @@ -@celo-contracts=contracts/ -@test-sol=test-sol -@lib=lib \ No newline at end of file diff --git a/packages/protocol/runTests.js b/packages/protocol/runTests.js deleted file mode 100644 index 747bfc104..000000000 --- a/packages/protocol/runTests.js +++ /dev/null @@ -1,92 +0,0 @@ -const ganache = require('ganache') -const glob = require('glob-fs')({ - gitignore: false, -}) -const { exec, waitForPortOpen } = require('./lib/test-utils') -const minimist = require('minimist') -const networkName = 'development' -const network = require('./truffle-config.js').networks[networkName] - -const sleep = (seconds) => new Promise((resolve) => setTimeout(resolve, 1000 * seconds)) - -// As documented https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables -const isCI = process.env.CI === 'true' - -async function startGanache() { - const server = ganache.server({ - logging: { quiet: true }, - wallet: { mnemonic: network.mnemonic, defaultBalance: network.defaultBalance }, - miner: { - blockGasLimit: 30000000, - defaultGasPrice: network.gasPrice, - }, - chain: { - networkId: network.network_id, - chainId: 1, - allowUnlimitedContractSize: true, - allowUnlimitedInitCodeSize: true, - }, - }) - - server.listen(8545, (err, blockchain) => { - if (err) throw err - blockchain - }) - - return async () => - await server.close((err) => { - if (err) throw err - }) -} - -async function test() { - const argv = minimist(process.argv.slice(2), { - boolean: ['gas', 'coverage', 'verbose-rpc'], - }) - - try { - console.info('Starting Ganache ...') - const closeGanache = await startGanache() - if (isCI) { - // If we are running on circle ci we need to wait for ganache to be up. - await waitForPortOpen('localhost', 8545, 120) - } - - // --reset is a hack to trick truffle into using 20M gas. - let testArgs = ['run', 'truffle', 'test', '--reset'] // Adding config doesn't seem to do much --config truffle-confisg0.8.js - if (argv['verbose-rpc']) { - testArgs.push('--verbose-rpc') - } - if (argv.coverage) { - testArgs = testArgs.concat(['--network', 'coverage']) - } else { - testArgs = testArgs.concat(['--network', networkName]) - } - if (argv.gas) { - testArgs = testArgs.concat(['--color', '--gas']) - } - - const testGlob = - argv._.length > 0 - ? argv._.map((testName) => - testName.endsWith('/') ? `test/${testName}\*\*/*.ts` : `test/\*\*/${testName}.ts` - ).join(' ') - : `test/\*\*/*.ts` - const testFiles = glob.readdirSync(testGlob) - if (testFiles.length === 0) { - // tslint:disable-next-line: no-console - console.error(`No test files matched with ${testGlob}`) - process.exit(1) - } - testArgs = testArgs.concat(testFiles) - - await exec('yarn', testArgs) - await closeGanache() - } catch (e) { - // tslint:disable-next-line: no-console - console.error(e.stdout ? e.stdout : e) - process.nextTick(() => process.exit(1)) - } -} - -test() diff --git a/packages/protocol/scripts/bash/backupmigrations.sh b/packages/protocol/scripts/bash/backupmigrations.sh deleted file mode 100755 index 1e324b3e0..000000000 --- a/packages/protocol/scripts/bash/backupmigrations.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/bash - -if [ -d migrations.bak ]; then - echo Replacing migrations - rm -rf migrations - mv migrations.bak migrations -else - echo Backing up migrations - mv migrations migrations.bak - mkdir migrations - - # Migration 0 always needs to be present - cp migrations.bak/00_initial_migration.* migrations/ - - # Uncomment lines for whichever migrations you actually do need. - # Note that some migrations depend on others (for example, many contracts - # require libraries to have been migrated, so you might need migration 1 to be - # uncommented). - cp migrations.bak/01_libraries.* migrations/ - # cp migrations.bak/02_registry.* migrations/ - # cp migrations.bak/03_freezer.* migrations/ - # cp migrations.bak/03_whitelist.* migrations/ - # cp migrations.bak/04_goldtoken.* migrations/ - # cp migrations.bak/05_sortedoracles.* migrations/ - # cp migrations.bak/06_gaspriceminimum.* migrations/ - # cp migrations.bak/07_reserve_spender_multisig.* migrations/ - # cp migrations.bak/08_reserve.* migrations/ - # cp migrations.bak/09_0_stabletoken_USD.* migrations/ - # cp migrations.bak/09_01_stableToken_EUR.* migrations/ - # cp migrations.bak/09_02_stableToken_BRL.* migrations/ - # cp migrations.bak/10_0_exchange_USD.* migrations/ - # cp migrations.bak/10_01_exchange_EUR.* migrations/ - # cp migrations.bak/10_02_exchange_BRL.* migrations/ - # cp migrations.bak/11_accounts.* migrations/ - # cp migrations.bak/12_lockedgold.* migrations/ - # cp migrations.bak/13_validators.* migrations/ - # cp migrations.bak/14_election.* migrations/ - # cp migrations.bak/15_epoch_rewards.* migrations/ - # cp migrations.bak/16_random.* migrations/ - # cp migrations.bak/17_attestations.* migrations/ - # cp migrations.bak/18_escrow.* migrations/ - # cp migrations.bak/19_blockchainparams.* migrations/ - # cp migrations.bak/20_governance_slasher.* migrations/ - # cp migrations.bak/21_double_signing_slasher.* migrations/ - # cp migrations.bak/22_downtime_slasher.* migrations/ - # cp migrations.bak/23_governance_approver_multisig.* migrations/ - # cp migrations.bak/24_grandamento.* migrations/ - # cp migrations.bak/25_stableToken_registry.* migrations/ - # cp migrations.bak/26_federated_attestations.* migrations/ - # cp migrations.bak/27_odispayments.* migrations/ - # cp migrations.bak/28_governance.* migrations/ - # cp migrations.bak/29_elect_validators.* migrations/ -fi diff --git a/packages/protocol/scripts/bash/check-versions.sh b/packages/protocol/scripts/bash/check-versions.sh deleted file mode 100755 index e001a5004..000000000 --- a/packages/protocol/scripts/bash/check-versions.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Checks that the contract version numbers in a provided branch are as expected given -# a released branch. -# -# Flags: -# -a: Old branch containing smart contracts, which has likely been released. -# -b: New branch containing smart contracts, on which version numbers may be updated. -# -r: Path that the contract compatibility report should be written to. -# -l: Path to a file to which logs should be appended - -BRANCH="" -NEW_BRANCH="" -REPORT="" -LOG_FILE="/tmp/celo-check-versions.log" - -while getopts 'a:b:r:l:i' flag; do - case "${flag}" in - a) BRANCH="${OPTARG}" ;; - b) NEW_BRANCH="${OPTARG}" ;; - r) REPORT="${OPTARG}" ;; - l) LOG_FILE="${OPTARG}" ;; - *) error "Unexpected option ${flag}" ;; - esac -done - -[ -z "$BRANCH" ] && echo "Need to set the old branch via the -a flag" && exit 1; -[ -z "$NEW_BRANCH" ] && echo "Need to set the new branch via the -b flag" && exit 1; - -# CONTRACT_EXCLUSION_REGEX imported from here -source scripts/bash/contract-exclusion-regex.sh - -REPORT_FLAG="" -if [ ! -z "$REPORT" ]; then - REPORT_FLAG="--output_file "$REPORT -fi - -source scripts/bash/release-lib.sh - -build_tag $BRANCH $LOG_FILE -BRANCH_BUILD_DIR=$BUILD_DIR -build_tag $NEW_BRANCH $LOG_FILE -NEW_BRANCH_BUILD_DIR=$BUILD_DIR - -# check-backward script uses migrationsConfig -echo " - Checkout migrationsConfig.js at $NEW_BRANCH" -CURRENT_HASH=`git log -n 1 --oneline | cut -c 1-9` -git checkout $NEW_BRANCH -- migrationsConfig.js - -yarn ts-node scripts/check-backward.ts sem_check \ - --old_contracts $BRANCH_BUILD_DIR/contracts \ - --new_contracts $NEW_BRANCH_BUILD_DIR/contracts \ - --exclude $CONTRACT_EXCLUSION_REGEX \ - $REPORT_FLAG - -git checkout $CURRENT_HASH -- migrationsConfig.js diff --git a/packages/protocol/scripts/bash/console.sh b/packages/protocol/scripts/bash/console.sh deleted file mode 100755 index 3580bdc8c..000000000 --- a/packages/protocol/scripts/bash/console.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Opens an interactive node+Truffle console connected to an Ethereum network. -# -# Flags: -# -n : the network to connect to -# -f: Boolean flag to indicate if the Forno service should be used to connect to -# the network - -NETWORK="" -FORNO="" - -while getopts 'n:f' flag; do - case "${flag}" in - n) NETWORK="$OPTARG" ;; - f) FORNO="--forno" ;; - *) error "Unexpected option ${flag}" ;; - esac -done - -[ -z "$NETWORK" ] && echo "Need to set the NETWORK via the -n flag" && exit 1; - -if ! nc -z 127.0.0.1 8545 && [ -z $FORNO ] ; then - echo "Port 8545 not open" - exit 1 -fi - -yarn run truffle console --network $NETWORK --contracts_build_directory $PWD/build/contracts $FORNO diff --git a/packages/protocol/scripts/bash/contract-exclusion-regex.sh b/packages/protocol/scripts/bash/contract-exclusion-regex.sh deleted file mode 100644 index 27a44b06a..000000000 --- a/packages/protocol/scripts/bash/contract-exclusion-regex.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Exclude test contracts, mock contracts, contract interfaces, Proxy contracts, inlined libraries, -# MultiSig contracts, and the ReleaseGold contract. -CONTRACT_EXCLUSION_REGEX=".*Test|Mock.*|I[A-Z].*|.*Proxy|MultiSig.*|ReleaseGold|SlasherUtil|UsingPrecompiles" - -# Before CR7, UsingRegistry and UsingRegistryV2 had been deployed, they need to keep getting deployed to keep the release reports without changes. -VERSION_NUMBER=$(echo "$BRANCH" | tr -dc '0-9') - -if [ $VERSION_NUMBER -gt 6 ] - then - CONTRACT_EXCLUSION_REGEX="$CONTRACT_EXCLUSION_REGEX|^UsingRegistry" -fi - -if [ $VERSION_NUMBER -gt 8 ] - then - CONTRACT_EXCLUSION_REGEX="$CONTRACT_EXCLUSION_REGEX|^Ownable|Initializable|BLS12_377Passthrough|BLS12_381Passthrough]UniswapV2ERC20" -fi - - # https://github.com/celo-org/celo-monorepo/issues/10435 - # SortedOracles is currently not deployable - # after fixing that this should be modified to VERSION_NUMBER==10 -if [ $VERSION_NUMBER -gt 9 ] - then - CONTRACT_EXCLUSION_REGEX="$CONTRACT_EXCLUSION_REGEX|SortedOracles" -fi - -# TODO remove this after merge by fixing the report creation scipt to include GasPriceMinimum (0.8 contracts) -# https://github.com/celo-org/celo-monorepo/issues/10567 -if [ $VERSION_NUMBER -gt 9 ] - then - CONTRACT_EXCLUSION_REGEX="$CONTRACT_EXCLUSION_REGEX|GasPriceMinimum" -fi diff --git a/packages/protocol/scripts/bash/deploy_release_contracts.sh b/packages/protocol/scripts/bash/deploy_release_contracts.sh deleted file mode 100755 index 2bbb7fa2b..000000000 --- a/packages/protocol/scripts/bash/deploy_release_contracts.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Deploys all grants detailed in `GRANTS_FILE` from the corresponding entity. -# -# Flags: -# -n: Name of the network to upgrade -# -f: Address of the account deploying the grant -# -g: File containing grant information -# -s: (Optional) Amount of gold for beneficiary to start with for transactions -# -d: (Optional) File to read deployed grants from and to output deployed grants to -# -o: (Optional) File to output results to -# -r: (Optional) Reply "yes" to prompts about deploying grants (Be careful!) -# -# Example: -# `./scripts/bash/deploy_release_contracts.sh -n development -f 0x5409ED021D9299bf6814279A6A1411A7e866A631 -g scripts/truffle/releaseGoldExampleConfigs.json` - -NETWORK="" -GRANTS_FILE="" -FROM="" -START_GOLD="" -DEPLOYED_GRANTS="" -OUTPUT_FILE="" -REALLY="" - -while getopts 'n:f:g:s:d:o:r:' flag; do - case "${flag}" in - n) NETWORK="$OPTARG" ;; - f) FROM="${OPTARG}" ;; - g) GRANTS_FILE="${OPTARG}" ;; - s) START_GOLD="${OPTARG}" ;; - d) DEPLOYED_GRANTS="${OPTARG}" ;; - o) OUTPUT_FILE="${OPTARG}" ;; - r) REALLY="--yesreally" ;; - *) error "Unexpected option ${flag}" ;; - esac -done - -[ -z "$NETWORK" ] && echo "Need to set the NETWORK via the -n flag" && exit 1; -[ -z "$FROM" ] && echo "Need to set the FROM address vai the -f flag" && exit 1; -[ -z "$GRANTS_FILE" ] && echo "Need to set the GRANTS_FILE via the -g flag" && exit 1; -[ -z "$START_GOLD" ] && echo "No starting gold provided via -s flag: defaulting to 1cGld" && START_GOLD=1; -[ -z "$DEPLOYED_GRANTS" ] && echo 'No deployed grants file provided via -d flag: defaulting to `scripts/truffle/deployedGrants.json`' && DEPLOYED_GRANTS="scripts/truffle/deployedGrants.json" -[ -z "$OUTPUT_FILE" ] && echo "Need to set output file via the -o flag" && exit 1; - -CONTRACT_ARTIFACTS_DIR="$PWD/build" - -if [[ ! -d "$CONTRACT_ARTIFACTS_DIR" ]]; then - echo "Error: no contract artifacts found in $CONTRACT_ARTIFACTS_DIR. Use download-artifacts to obtain them, or build them locally." >&2 - exit 1 -fi - -if ! nc -z 127.0.0.1 8545 ; then - echo "Warning: port 8545 not open" >&2 -fi - -yarn run build:ts && \ -yarn run truffle exec ./scripts/truffle/deploy_release_contracts.js \ - --network $NETWORK --from $FROM --grants $GRANTS_FILE --start_gold $START_GOLD --deployed_grants $DEPLOYED_GRANTS --output_file $OUTPUT_FILE $REALLY --build_directory $CONTRACT_ARTIFACTS_DIR \ diff --git a/packages/protocol/scripts/bash/download_artifacts.sh b/packages/protocol/scripts/bash/download_artifacts.sh deleted file mode 100755 index 41f3b4d58..000000000 --- a/packages/protocol/scripts/bash/download_artifacts.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Downloads contract build artifacts from GCS -# -# Flags: -# -b: Name of the bucket to download artifacts from -# -n: Name of the network to download artifacts for - -ARTIFACT_BUCKET="contract_artifacts" -NETWORK="" -while getopts 'b:n:' flag; do - case "${flag}" in - b) ARTIFACT_BUCKET="${OPTARG:-contract_artifacts}" ;; - n) NETWORK="${OPTARG}" ;; - *) error "Unexpected option ${flag}" ;; - esac -done -[ -z "$NETWORK" ] && echo "Need to set the NETWORK via the -n flag" && exit 1; - -TARBALL=.$NETWORK-$RANDOM.tar.gz - -# For some reason, unable to extract sometimes -curl https://www.googleapis.com/storage/v1/b/$ARTIFACT_BUCKET/o/$NETWORK?alt=media > $TARBALL \ - && tar -zxvf $TARBALL \ - && rm $TARBALL diff --git a/packages/protocol/scripts/bash/ganache.sh b/packages/protocol/scripts/bash/ganache.sh deleted file mode 100755 index 822adb1ff..000000000 --- a/packages/protocol/scripts/bash/ganache.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Runs ganache with the mnemonic used in our tests. - -yarn run ganache \ - --wallet.mnemonic='concert load couple harbor equip island argue ramp clarify fence smart topic' \ - --miner.defaultGasPrice=0 \ - --chain.networkId=1101 \ - --miner.blockGasLimit=20000000 \ - --wallet.defaultBalance=200000000 \ - --chain.allowUnlimitedContractSize=true \ - --chain.chainId=1 \ diff --git a/packages/protocol/scripts/bash/ganache_devchain.sh b/packages/protocol/scripts/bash/ganache_devchain.sh deleted file mode 100755 index 174ad8adf..000000000 --- a/packages/protocol/scripts/bash/ganache_devchain.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -DATA_DIR="" - -while getopts 'd:' flag; do - case "${flag}" in - d) DATA_DIR="${OPTARG}" ;; - *) error "Unexpected option ${flag}" ;; - esac -done - -[ -z "$DATA_DIR" ] && echo "Need to set the datadir path via the -d flag" && exit 1; - -yarn run ganache \ - --detach \ - --wallet.mnemonic='concert load couple harbor equip island argue ramp clarify fence smart topic' \ - --miner.defaultGasPrice=0 \ - --miner.blockGasLimit=20000000 \ - --wallet.defaultBalance=200000000 \ - --chain.networkId=1101 \ - --chain.allowUnlimitedContractSize=true \ - --chain.chainId=1 \ - --chain.hardfork='istanbul' \ - --database.dbPath=$DATA_DIR \ diff --git a/packages/protocol/scripts/bash/generate-old-devchain-and-build.sh b/packages/protocol/scripts/bash/generate-old-devchain-and-build.sh deleted file mode 100755 index 373edb93e..000000000 --- a/packages/protocol/scripts/bash/generate-old-devchain-and-build.sh +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -source ./scripts/bash/utils.sh - -# Generates a local network of a target git ref -# -# Flags: -# -b: Branch containing smart contracts that currently comprise the Celo protocol -# -l: Path to a file to which logs should be appended - -BRANCH="" -NETWORK="" -FORNO="" -BUILD_DIR="" -LOG_FILE="/dev/null" -GRANTS_FILE="" - -while getopts ':b:rl:d:g:' flag; do - case "${flag}" in - b) BRANCH="${OPTARG}" ;; - l) LOG_FILE="${OPTARG}" ;; - d) BUILD_DIR="${OPTARG}" ;; - g) GRANTS_FILE="${OPTARG}";; - *) error "Unexpected option ${flag}" ;; - esac -done - -[ -z "$BRANCH" ] && echo "Need to set the branch via the -b flag" && exit 1; - - -REMOTE_URL=$(git remote get-url origin) - - -# Create temporary directory -TMP_DIR=$(mktemp -d) -echo "Using temporary directory $TMP_DIR" - -[ -z "$BUILD_DIR" ] && BUILD_DIR=$(echo "build/$(echo $BRANCH | sed -e 's/\//_/g')"); - -echo "Using build directory $BUILD_DIR" -rm -rf $BUILD_DIR && mkdir -p $BUILD_DIR -BUILD_DIR_ABOSLUTE=$(cd "$BUILD_DIR" && pwd || echo "Error: Failed to find directory") -echo "ABSOLUTE BUILD DIR: $BUILD_DIR_ABOSLUTE" - - -echo "- Checkout source code at $BRANCH" and remote url $REMOTE_URL -# Clone the repository into the temporary directory -git clone $REMOTE_URL "$TMP_DIR/repo" --branch "$BRANCH" --single-branch -cd "$TMP_DIR/repo" - -# Redirection of logs -exec 2>>$LOG_FILE >> $LOG_FILE - -echo "- Build monorepo (contract artifacts, migrations, + all dependencies)" - -# Here, replace the 'yarn' commands as necessary to work within the temp directory structure -yarn run reset -yarn install -yarn run clean -RELEASE_TAG="" yarn build -cd packages/protocol - -echo "- Create local network" -if [ -z "$GRANTS_FILE" ]; then - yarn devchain generate-tar "$PWD/devchain.tar.gz" -else - yarn devchain generate-tar "$PWD/devchain.tar.gz" --release_gold_contracts "$GRANTS_FILE" -fi - -echo "moving contracts from build/contracts to $BUILD_DIR_ABOSLUTE" -mv build/contracts $BUILD_DIR_ABOSLUTE -echo "moving $PWD/devchain.tar.gz to $BUILD_DIR_ABOSLUTE" -mv "$PWD/devchain.tar.gz" $BUILD_DIR_ABOSLUTE/. - -echo "removing tmp directory $TMP_DIR" -rm -rf "$TMP_DIR" diff --git a/packages/protocol/scripts/bash/govern.sh b/packages/protocol/scripts/bash/govern.sh deleted file mode 100755 index f257f085b..000000000 --- a/packages/protocol/scripts/bash/govern.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Allows users submit (and possibly execute) MultiSig transactions. -# -# Flags: -# -c: Function to run, e.g. stableToken.setMinter(0x1234) -# -n: Name of the network to govern - -CMD="" -NETWORK="" - -while getopts 'c:n:' flag; do - case "${flag}" in - c) CMD="${OPTARG}" ;; - n) NETWORK="$OPTARG" ;; - *) error "Unexpected option ${flag}" ;; - esac -done - -[ -z "$NETWORK" ] && echo "Need to set the NETWORK via the -n flag" && exit 1; - -if ! nc -z 127.0.0.1 8545 ; then - echo "Port 8545 not open" - exit 1 -fi - -yarn run build && \ -yarn run truffle exec ./scripts/truffle/govern.js \ - --network $NETWORK --build_directory $PWD/build/$NETWORK --command "$CMD" diff --git a/packages/protocol/scripts/bash/init_network.sh b/packages/protocol/scripts/bash/init_network.sh deleted file mode 100755 index 1461658b7..000000000 --- a/packages/protocol/scripts/bash/init_network.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Runs all truffle migrations in protocol/migrations/ -# -# Flags: -# -n: Name of the network to migrate to - -yarn run migrate -r "$@" && yarn run set_block_gas_limit "$@" diff --git a/packages/protocol/scripts/bash/make-release.sh b/packages/protocol/scripts/bash/make-release.sh deleted file mode 100755 index 73e688c9e..000000000 --- a/packages/protocol/scripts/bash/make-release.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Checks that the contract version numbers in a provided branch are as expected given -# a released branch. -# -# Flags: -# -n: The network to deploy to. -# -b: Branch to build contracts from. -# -p: Path that the governance proposal should be written to. -# -i: Path to the data needed to initialize contracts. -# -r: Path to the contract compatibility report. -# -d: Whether to dry-run this deploy -# -f: Address to sign transactions from. -# -l: Path to the canonical library mapping. -# -F: Whether to use the forno endpoint - -NETWORK="" -PROPOSAL="" -BRANCH="" -INITIALIZE_DATA="" -REPORT="" -DRYRUN="" -FROM="" -LIBRARIES="" -FORNO="" - -while getopts 'b:n:p:i:r:df:l:F' flag; do - case "${flag}" in - b) BRANCH="${OPTARG}" ;; - n) NETWORK="${OPTARG}" ;; - p) PROPOSAL="${OPTARG}" ;; - i) INITIALIZE_DATA="${OPTARG}" ;; - r) REPORT="${OPTARG}" ;; - d) DRYRUN="--dry_run" ;; - F) FORNO="--forno" ;; - f) FROM="${OPTARG}" ;; - l) LIBRARIES="${OPTARG}" ;; - *) error "Unexpected option ${flag}" ;; - esac -done - -[ -z "$NETWORK" ] && echo "Need to set the NETWORK via the -n flag" && exit 1; -[ -z "$BRANCH" ] && echo "Need to set the build branch via the -b flag" && exit 1; -[ -z "$PROPOSAL" ] && echo "Need to set the proposal outfile via the -p flag" && exit 1; -[ -z "$INITIALIZE_DATA" ] && echo "Need to set the initialization data via the -i flag" && exit 1; -[ -z "$REPORT" ] && echo "Need to set the compatibility report input via the -r flag" && exit 1; -[ -z "$LIBRARIES" ] && echo "Need to set the library mapping input via the -l flag" && exit 1; - -source scripts/bash/release-lib.sh -build_tag $BRANCH "/dev/stdout" - -yarn run truffle exec ./scripts/truffle/make-release.js \ - --network $NETWORK \ - --build_directory $BUILD_DIR \ - --report $REPORT \ - --librariesFile $LIBRARIES \ - --proposal $PROPOSAL \ - --from $FROM \ - --branch $BRANCH \ - --initialize_data $INITIALIZE_DATA $DRYRUN $FORNO diff --git a/packages/protocol/scripts/bash/migrate.sh b/packages/protocol/scripts/bash/migrate.sh deleted file mode 100755 index 22c358bba..000000000 --- a/packages/protocol/scripts/bash/migrate.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Runs unmigrated truffle migrations in protocol/migrations/ -# -# Flags: -# -n: Name of the network to migrate to -# -r: Reset network state by running all migrations - -TRUFFLE_OVERRIDE="" -MIGRATION_OVERRIDE="" -NETWORK="" -RESET="" -# https://github.com/trufflesuite/truffle-migrate/blob/develop/index.js#L161 -# Default to larger than the number of contracts we will ever have - -while getopts 'n:rt:f:c:m:' flag; do - case "${flag}" in - n) NETWORK="$OPTARG" ;; - r) RESET="--reset" ;; - t) TO="$OPTARG" ;; - f) FROM="$OPTARG" ;; - c) TRUFFLE_OVERRIDE="$OPTARG" ;; - m) MIGRATION_OVERRIDE="$OPTARG" ;; - *) error "Unexpected option ${flag}" ;; - esac -done - -[ -z "$NETWORK" ] && echo "Need to set the NETWORK via the -n flag" && exit 1; - -if ! nc -z 127.0.0.1 8545 ; then - echo "Port 8545 not open" - exit 1 -fi - -yarn run build && \ -echo "Migrating contracts migrations${FROM:+ from number $FROM}${TO:+ up to number $TO}" && \ -yarn run truffle migrate --compile-all --network $NETWORK --build_directory $PWD/build/$NETWORK $RESET \ - ${TO:+ --to $TO} \ - ${FROM:+ -f $FROM} \ - --truffle_override "$TRUFFLE_OVERRIDE" \ - --migration_override "$MIGRATION_OVERRIDE" diff --git a/packages/protocol/scripts/bash/quicktest.sh b/packages/protocol/scripts/bash/quicktest.sh deleted file mode 100755 index 35ad0785f..000000000 --- a/packages/protocol/scripts/bash/quicktest.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env bash - -# Use this script if you want quick test iterations. -# Compared to the normal test command, this script will: -# 1. not run the pretest script of building solidity (will still be run as part of truffle test) -# and compiling typescript. This works because truffle can run typescript "natively". -# 2. only migrate selected migrations as set in `backupmigrations.sh` (you'll likely need at -# least one compilation step since truffle seems to only run compiled migrations) -# - -rm test/**/*.js -./scripts/bash/backupmigrations.sh -node runTests.js "$@" -./scripts/bash/backupmigrations.sh diff --git a/packages/protocol/scripts/bash/release-lib.sh b/packages/protocol/scripts/bash/release-lib.sh deleted file mode 100644 index 094232891..000000000 --- a/packages/protocol/scripts/bash/release-lib.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env bash - -# USAGE: build_tag -# This function: -# 1. checks out the given branch -# 2. builds contracts -# 3. returns to original branch -# piping output of any commands to the specified log file. -# Sets $BUILD_DIR to the directory where resulting build artifacts may be found. -function build_tag() { - local BRANCH="$1" - local LOG_FILE="$2" - - local CURRENT_HASH=`git log -n 1 --oneline | cut -c 1-9` - - git fetch origin +'refs/tags/core-contracts.v*:refs/tags/core-contracts.v*' >> $LOG_FILE - - echo " - Checkout contracts source code at $BRANCH" - BUILD_DIR=$(echo build/$(echo $BRANCH | sed -e 's/\//_/g')) - [ -d contracts ] && rm -r contracts - - # this remove is necesary because when bringing a contracts folder from previous commit - # if a folder didn't exist in the past, git will not remove the current one - # trying to compile it and leading to potental build errors - - rm -rf contracts* - git checkout $BRANCH -- contracts* 2>>$LOG_FILE >> $LOG_FILE - if [ ! -d $BUILD_DIR ]; then - echo " - Build contract artifacts at $BUILD_DIR" - BUILD_DIR=$BUILD_DIR yarn build:sol >> $LOG_FILE - else - echo " - Contract artifacts already built at $BUILD_DIR" - fi - - [ -d contracts ] && rm -r contracts - git checkout $CURRENT_HASH -- contracts 2>>$LOG_FILE >> $LOG_FILE -} diff --git a/packages/protocol/scripts/bash/release-on-devchain.sh b/packages/protocol/scripts/bash/release-on-devchain.sh deleted file mode 100755 index 81d965eb3..000000000 --- a/packages/protocol/scripts/bash/release-on-devchain.sh +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -source ./scripts/bash/utils.sh - -# Simulates a release of the current contracts against a target git ref on a local network -# -# Flags: -# -b: Branch containing smart contracts that currently comprise the Celo protocol -# -l: Path to a file to which logs should be appended - -BRANCH="" -BUILD_DIR="" -RE_BUILD_REPO="" - -while getopts 'b:l:d:' flag; do - case "${flag}" in - b) BRANCH="${OPTARG}" ;; - d) BUILD_DIR="${OPTARG}" ;; - *) error "Unexpected option ${flag}" ;; - esac -done - -[ -z "$BRANCH" ] && echo "Need to set the branch via the -b flag" && exit 1; - -# if BUILD_DIR was not set as a parameter, we generate the build and the chain for that specific branch -if [ -z "$BUILD_DIR" ] -then - RE_BUILD_REPO="yes" - BUILD_DIR=$(echo build/$(echo $BRANCH | sed -e 's/\//_/g')) -fi - - -echo "- Run local network" -yarn devchain run-tar-in-bg packages/protocol/$BUILD_DIR/devchain.tar.gz - -GANACHE_PID= -if command -v lsof; then - GANACHE_PID=`lsof -i tcp:8545 | tail -n 1 | awk '{print $2}'` - echo "Network started with PID $GANACHE_PID, if exit 1, you will need to manually stop the process" -fi - -echo "- Verify bytecode of the network" - -yarn run truffle exec ./scripts/truffle/verify-bytecode.js --network development --build_artifacts $BUILD_DIR/contracts --branch $BRANCH --librariesFile libraries.json - -echo "- Check versions of current branch" -# From check-versions.sh - -BASE_COMMIT=$(git rev-parse HEAD) -echo " - Base commit $BASE_COMMIT" -echo " - Checkout migrationsConfig.js at $BRANCH" -git checkout $BRANCH -- migrationsConfig.js - -source scripts/bash/contract-exclusion-regex.sh -yarn ts-node scripts/check-backward.ts sem_check --old_contracts $BUILD_DIR/contracts --new_contracts build/contracts --exclude $CONTRACT_EXCLUSION_REGEX --output_file report.json - -echo "- Clean git modified file" -git restore migrationsConfig.js - - -# From make-release.sh -echo "- Deploy release of current branch" -INITIALIZATION_FILE=`ls releaseData/initializationData/release*.json | sort -V | tail -n 1 | xargs realpath` -yarn truffle exec --network development ./scripts/truffle/make-release.js --build_directory build/ --branch $BRANCH --report report.json --proposal proposal.json --librariesFile libraries.json --initialize_data $INITIALIZATION_FILE - -# From verify-release.sh -echo "- Verify release" -yarn truffle exec --network development ./scripts/truffle/verify-bytecode.js --build_artifacts build/contracts --proposal ../../proposal.json --branch $BRANCH --initialize_data $INITIALIZATION_FILE - -if [[ -n $GANACHE_PID ]]; then - kill $GANACHE_PID -fi diff --git a/packages/protocol/scripts/bash/release-snapshots.sh b/packages/protocol/scripts/bash/release-snapshots.sh deleted file mode 100755 index c7b6a8039..000000000 --- a/packages/protocol/scripts/bash/release-snapshots.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -N=`echo -n $RELEASE_TAG | tail -c -1` - -for i in `eval echo {1..$N}` -do - yarn check-versions \ - -a "core-contracts.v$(($i - 1))" \ - -b "core-contracts.v$i" \ - -r "releaseData/versionReports/release$i-report.json" -done diff --git a/packages/protocol/scripts/bash/revoke_contracts.sh b/packages/protocol/scripts/bash/revoke_contracts.sh deleted file mode 100755 index 4f0765451..000000000 --- a/packages/protocol/scripts/bash/revoke_contracts.sh +++ /dev/null @@ -1,67 +0,0 @@ -#! /usr/bin/env bash -set -euo pipefail -rejects=() - -if [ "$#" -ne 1 ]; then - echo "Expected usage: ./revoke_contracts.sh contracts.txt" - echo "contracts.txt should include contracts you'd like to revoke and refund, one address per line" - exit 1 -fi - -for contract in $(<"$1"); do - echo "Contract $contract" - - # Check that account has been created - accountCreated=1 - celocli lockedgold:show "$contract" > /dev/null 2>&1 || accountCreated=0 - if [ $accountCreated -ne 0 ]; then - - # Check that CELO has been unlocked - lockedgold=$(celocli lockedgold:show "$contract") - total=$(echo "$lockedgold" | grep -o "total: [0-9]*" | cut -f2 -d : | tr -d '[:space:]') - if [ "$total" != "0" ]; then - echo "Reject $contract: locked CELO > 0" - rejects+=( $contract ) - continue - fi - - # Check that withdrawals are available - if [ -z $(echo "$lockedgold" | grep -o "time: [0-9]*" | cut -f2 -d :) ]; then - echo "No pending withdrawals" - else - pendingTimes=$(echo "$lockedgold" | grep -o "time: [0-9]*" | cut -f2 -d :) - now=$(date +%s) - while IFS= read -r line - do - if [ "$line" -ge "$now" ]; then - echo "Pending withdrawal not ready, rejecting $contract" - rejects+=( $contract ) - continue 2 - fi - done < <(printf '%s\n' "$pendingTimes") - fi - fi - - contractExists=1 - celocli releasegold:revoke --contract "$contract" --yesreally --useLedger > /dev/null || contractExists=0 - if [ "$contractExists" -eq 0 ]; then - echo "Contract doesn't exist, rejecting $contract" - rejects+=( $contract ) - continue - fi - if [ "$accountCreated" -ne 0 ]; then - celocli releasegold:locked-gold --contract "$contract" --action withdraw --value "$total" --yes --useLedger > /dev/null - fi - celocli releasegold:refund-and-finalize --contract "$contract" --useLedger > /dev/null - -done - -echo "" -echo "-----------------------------------" -echo "-----------------------------------" -echo "-----------------------------------" -echo "" -echo "Rejects:" -for reject in ${rejects[@]}; do - echo "$reject" -done \ No newline at end of file diff --git a/packages/protocol/scripts/bash/set_block_gas_limit.sh b/packages/protocol/scripts/bash/set_block_gas_limit.sh deleted file mode 100755 index c260ed298..000000000 --- a/packages/protocol/scripts/bash/set_block_gas_limit.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Sets block gas limit and turns ownership of contract over to governance -# -# Flags: -# -n: Name of the network to migrate to - -TRUFFLE_OVERRIDE="" -MIGRATION_OVERRIDE="" -NETWORK="" -# https://github.com/trufflesuite/truffle-migrate/blob/develop/index.js#L161 -# Default to larger than the number of contracts we will ever have - -while getopts 'n:rt:f:c:m:' flag; do - case "${flag}" in - n) NETWORK="$OPTARG" ;; - c) TRUFFLE_OVERRIDE="$OPTARG" ;; - m) MIGRATION_OVERRIDE="$OPTARG" ;; - t) ;; - *) error "Unexpected option ${flag}" ;; - esac -done - -[ -z "$NETWORK" ] && echo "Need to set the NETWORK via the -n flag" && exit 1; - -if ! nc -z 127.0.0.1 8545 ; then - echo "Port 8545 not open" - exit 1 -fi - -yarn run truffle exec ./scripts/truffle/set_block_gas_limit.js \ - --network $NETWORK --build_directory $PWD/build/$NETWORK --truffle_override "$TRUFFLE_OVERRIDE" \ - --migration_override "$MIGRATION_OVERRIDE" diff --git a/packages/protocol/scripts/bash/set_exchange_rate.sh b/packages/protocol/scripts/bash/set_exchange_rate.sh deleted file mode 100755 index ec54f5aac..000000000 --- a/packages/protocol/scripts/bash/set_exchange_rate.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Updates the Gold/Stable token exchange rate to the provided value, or, if a CSV of -# (timestamp, stableValue, goldValue) tuples is provided, updates the exchange rate to the value -# associated with the most recent timestamp less than or equal to the current time stamp. -# -# Flags: -# -f: Filepath to csv of (timestamp, stableValue, goldValue) tuples -# -n: name of the network defined in truffle-config.js to set the exchange rate on -# -s: StableToken component of exchange rate -# -g: GoldToken component of exchange rate -# -c: Override for truffle config - -NETWORK="" -FILE="" -GOLD_VALUE="" -STABLE_VALUE="" -CONFIG_OVERRIDE="" - -while getopts 'g:f:n:s:c:' flag; do - case "${flag}" in - n) NETWORK="$OPTARG" ;; - f) FILE="$OPTARG" ;; - s) STABLE_VALUE="$OPTARG" ;; - g) GOLD_VALUE="$OPTARG" ;; - c) CONFIG_OVERRIDE="$OPTARG" ;; - *) error "Unexpected option ${flag}" ;; - esac -done - -[ -z "$NETWORK" ] && echo "Need to set the NETWORK via the -n flag" && exit 1; - -yarn run download-artifacts -n $NETWORK && \ -yarn run build && \ -yarn run truffle exec ./scripts/truffle/set_exchange_rate.js \ - --network $NETWORK --stableValue $STABLE_VALUE --goldValue $GOLD_VALUE \ - --build_directory $PWD/build/$NETWORK --csv $FILE \ - --config_override "$CONFIG_OVERRIDE" diff --git a/packages/protocol/scripts/bash/transfer.sh b/packages/protocol/scripts/bash/transfer.sh deleted file mode 100755 index 9c8dfdbe3..000000000 --- a/packages/protocol/scripts/bash/transfer.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Transfers StableToken and Gold balances to an account -# -# Flags: -# -a: Address of the account who will receive the transfer -# -n: Name of the network to increment balances on - -ACCOUNT="" -NETWORK="" -DOLLARS="0" -GOLD="0" - -while getopts 'a:n:d:g:' flag; do - case "${flag}" in - a) ACCOUNT="$OPTARG" ;; - n) NETWORK="$OPTARG" ;; - d) DOLLARS="$OPTARG" ;; - g) GOLD="$OPTARG" ;; - *) error "Unexpected option ${flag}" ;; - esac -done - -[ -z "$NETWORK" ] && echo "Need to set the NETWORK via the -n flag" && exit 1; -[ -z "$ACCOUNT" ] && echo "Need to set the ACCOUNT via the -a flag" && exit 1; - -if ! nc -z 127.0.0.1 8545 ; then - echo "Port 8545 not open" - exit 1 -fi - -yarn run build && \ -yarn run truffle exec ./scripts/truffle/transfer.js \ - --network $NETWORK --stableValue $DOLLARS --goldValue $GOLD \ - --build_directory $PWD/build/$NETWORK --to $ACCOUNT diff --git a/packages/protocol/scripts/bash/upload_artifacts.sh b/packages/protocol/scripts/bash/upload_artifacts.sh deleted file mode 100755 index 10e82c71b..000000000 --- a/packages/protocol/scripts/bash/upload_artifacts.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Uploads contract build artifacts to GCS -# -# Flags: -# -b: Name of the bucket to upload artifacts to -# -n: Name of the network to upload artifacts for - -ARTIFACT_BUCKET="contract_artifacts" -NETWORK="" -while getopts 'b:n:' flag; do - case "${flag}" in - b) ARTIFACT_BUCKET="${OPTARG:-contract_artifacts}" ;; - n) NETWORK="${OPTARG}" ;; - *) error "Unexpected option ${flag}" ;; - esac -done -[ -z "$NETWORK" ] && echo "Need to set the NETWORK via the -n flag" && exit 1; - -TARBALL=$NETWORK.tar.gz - -tar -zcvf $TARBALL build/$NETWORK && \ - gsutil cp $TARBALL gs://$ARTIFACT_BUCKET/$NETWORK && \ - rm $TARBALL diff --git a/packages/protocol/scripts/bash/utils.sh b/packages/protocol/scripts/bash/utils.sh deleted file mode 100644 index 6490644f5..000000000 --- a/packages/protocol/scripts/bash/utils.sh +++ /dev/null @@ -1,29 +0,0 @@ -# USAGE: startInBgAndWaitForString -# This function will start `command` as a background process, but block until -# a line matching `pattern` appears on its standard output. -function startInBgAndWaitForString() { - # Grab the first argument and remove it from the argument list. - local patternToWaitFor=$1 - shift - - # The rest of the arguments are the command we will run. - local cmd=$@ - - # Create a named pipe. The command will write to it, and we will read from - # it to wait for the expected output. - local pipe=$(mktemp -u) - mkfifo $pipe - - # Execute the given command, directing its output to both STDOUT and the - # pipe we created. - $cmd | tee $pipe & - - local gotIt=0 - while [[ $gotIt != 1 ]]; do - local line - read line - if echo "$line" | grep "$patternToWaitFor" > /dev/null; then - gotIt=1 - fi - done <$pipe -} diff --git a/packages/protocol/scripts/bash/verify-deployed.sh b/packages/protocol/scripts/bash/verify-deployed.sh deleted file mode 100755 index bcb0aaba6..000000000 --- a/packages/protocol/scripts/bash/verify-deployed.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Checks that Solidity sources on a given branch correspond to bytecodes -# deployed to a Celo system deployed to the given network. -# -# Flags: -# -b: Branch containing smart contracts that currently comprise the Celo protocol -# -n: The network to check -# -f: Boolean flag to indicate if the Forno service should be used to connect to -# the network -# -l: Path to a file to which logs should be appended - -BRANCH="" -NETWORK="" -FORNO="" -LOG_FILE="/dev/stdout" - -while getopts 'b:n:fl:' flag; do - case "${flag}" in - b) BRANCH="${OPTARG}" ;; - n) NETWORK="${OPTARG}" ;; - f) FORNO="--forno" ;; - l) LOG_FILE="${OPTARG}" ;; - *) error "Unexpected option ${flag}" ;; - esac -done - -[ -z "$BRANCH" ] && echo "Need to set the branch via the -b flag" && exit 1; -[ -z "$NETWORK" ] && echo "Need to set the NETWORK via the -n flag" && exit 1; - -source scripts/bash/release-lib.sh -build_tag $BRANCH $LOG_FILE - -yarn run truffle exec ./scripts/truffle/verify-bytecode.js --network $NETWORK --build_artifacts $BUILD_DIR/contracts --branch $BRANCH --librariesFile "libraries.json" $FORNO diff --git a/packages/protocol/scripts/bash/verify-release.sh b/packages/protocol/scripts/bash/verify-release.sh deleted file mode 100755 index 42957f312..000000000 --- a/packages/protocol/scripts/bash/verify-release.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Checks that Solidity sources on a given branch correspond to bytecodes -# deployed to a Celo system deployed to the given network, as modified by a -# Governance proposal. -# -# Flags: -# -b: Branch containing smart contracts that are proposed to be deployed. -# -n: The network to check -# -p: The proposal JSON file -# -i: Path to the data needed to initialize contracts. -# -f: Boolean flag to indicate if the Forno service should be used to connect to -# the network -# -l: Path to a file to which logs should be appended - -BRANCH="" -NETWORK="" -PROPOSAL="" -FORNO="" -INITIALIZE_DATA="" -LOG_FILE="/tmp/celo-verify-release.log" - -while getopts 'b:n:p:fl:i:' flag; do - case "${flag}" in - b) BRANCH="${OPTARG}" ;; - n) NETWORK="${OPTARG}" ;; - i) INITIALIZE_DATA="--initialize_data $(realpath $OPTARG)" ;; - p) PROPOSAL="$(realpath $OPTARG)" ;; - f) FORNO="--forno" ;; - l) LOG_FILE="${OPTARG}" ;; - *) error "Unexpected option ${flag}" ;; - esac -done - -[ -z "$BRANCH" ] && echo "Need to set the branch via the -b flag" && exit 1; -[ -z "$NETWORK" ] && echo "Need to set the network via the -n flag" && exit 1; -[ -z "$PROPOSAL" ] && echo "Need to set the proposal via the -p flag" && exit 1; - -source scripts/bash/release-lib.sh -build_tag $BRANCH $LOG_FILE - -yarn run truffle exec ./scripts/truffle/verify-bytecode.js --network $NETWORK --build_artifacts $BUILD_DIR/contracts --branch $BRANCH --proposal $PROPOSAL $FORNO $INITIALIZE_DATA diff --git a/packages/protocol/scripts/bash/verify_release_gold_contracts.sh b/packages/protocol/scripts/bash/verify_release_gold_contracts.sh deleted file mode 100755 index 6e4437214..000000000 --- a/packages/protocol/scripts/bash/verify_release_gold_contracts.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Verify all contracts in CONTRACT_FILE match the configs in CONFIG_FILE -# -# Flags: -# -n: Name of the network to query -# -o: File output from deploy script containing contract information -# -c: File input to deploy script containing contract configs -# -# Example: -# `./scripts/bash/verify_release_gold_balances.sh -n development -o grantsOut.json -c releaseGoldExampleConfigs.json - -NETWORK="" -CONTRACT_JSON="" -CONFIG_JSON="" - -while getopts 'n:o:c:' flag; do - case "${flag}" in - n) NETWORK="$OPTARG" ;; - o) CONTRACT_JSON="${OPTARG}" ;; - c) CONFIG_JSON="${OPTARG}" ;; - *) error "Unexpected option ${flag}" ;; - esac -done - -[ -z "$NETWORK" ] && echo "Need to set the NETWORK via the -n flag" && exit 1; -[ -z "$CONTRACT_JSON" ] && echo "Need to set the CONTRACT_JSON file via the -o flag" && exit 1; -[ -z "$CONFIG_JSON" ] && echo "Need to set the CONFIG_JSON file via the -c flag" && exit 1; - -if ! nc -z 127.0.0.1 8545 ; then - echo "Port 8545 not open" - exit 1 -fi - -yarn run build && \ -yarn run truffle exec ./scripts/truffle/verify_release_gold_contracts.js \ - --network $NETWORK --contract_json $CONTRACT_JSON --config_json $CONFIG_JSON --build_directory $PWD/build/$NETWORK \ \ No newline at end of file diff --git a/packages/protocol/scripts/build.ts b/packages/protocol/scripts/build.ts deleted file mode 100644 index 93d6df471..000000000 --- a/packages/protocol/scripts/build.ts +++ /dev/null @@ -1,190 +0,0 @@ -/* tslint:disable no-console */ - -import Web3V1Celo from '@celo/typechain-target-web3-v1-celo' -import { execSync } from 'child_process' -import fsExtraPkg from 'fs-extra' -import minimist, { ParsedArgs } from 'minimist' -import path from 'path' -import { tsGenerator } from 'ts-generator' -import { contractPackages, CoreContracts, ImplContracts, Interfaces, ROOT_DIR } from './consts' - -const { existsSync, readJSONSync } = fsExtraPkg - -const BUILD_DIR = path.join(ROOT_DIR, process.env.BUILD_DIR ?? './build') - -function exec(cmd: string) { - return execSync(cmd, { cwd: ROOT_DIR, stdio: 'inherit' }) -} - -function hasEmptyBytecode(contract: any) { - return contract.bytecode === '0x' -} - -function compile({ coreContractsOnly, solidity: outdir }: BuildTargets) { - console.log(`protocol: Compiling solidity to ${outdir}`) - - // the reason to generate a different folder is to avoid path collisions, which could be very dangerous - for (const contractPackage of contractPackages) { - console.log(`Building Contracts for package ${contractPackage.name}`) - - const contractPath = path.join( - './', - contractPackage.folderPath, - contractPackage.path, - contractPackage.contractsFolder - ) - if (!existsSync(contractPath)) { - console.log(`Contract package named ${contractPackage.name} doesn't exist`) - continue - } - - exec( - `yarn run truffle compile --silent --contracts_directory=${contractPath} --contracts_build_directory=${outdir}/contracts-${contractPackage.name} --config ${contractPackage.truffleConfig}` // todo change to outdir - ) - } - - // compile everything else - exec( - `yarn run --silent truffle compile --contracts_directory="./contracts/" --build_directory=${outdir}` - ) - - const contracts = coreContractsOnly ? CoreContracts : ImplContracts - // check that there were no errors - for (const contractName of contracts) { - try { - const artifactPath = `${outdir}/contracts/${contractName}.json` - const artifactPath8 = `${outdir}/contracts-0.8/${contractName}.json` - let is08 = false - // This is issuing a warning: https://github.com/celo-org/celo-monorepo/issues/10564 - if (existsSync(artifactPath8)) { - is08 = true - } - const fileStr = readJSONSync(is08 ? artifactPath8 : artifactPath) - if (hasEmptyBytecode(fileStr)) { - console.error( - `${contractName} has empty bytecode. Maybe you forgot to fully implement an interface?` - ) - process.exit(1) - } - } catch (e) { - console.log(e) - console.debug( - `WARNING: ${contractName} artifact could not be fetched. Maybe it doesn't exist?` - ) - } - } -} - -function generateFilesForTruffle({ coreContractsOnly, truffleTypes: outdir }: BuildTargets) { - // tslint:disable-next-line - for (let externalContractPackage of contractPackages) { - const outdirExternal = outdir + '-' + externalContractPackage.name - console.log( - `protocol: Generating Truffle Types for external dependency ${externalContractPackage.name} to ${outdirExternal}` - ) - - const artifactPath = `${BUILD_DIR}/contracts-${externalContractPackage.name}/*.json` - exec( - `yarn run --silent typechain --target=truffle --outDir "${outdirExternal}" "${artifactPath}"` - ) - } - - console.log(`protocol: Generating Truffle Types to ${outdir}`) - exec(`rm -rf "${outdir}"`) - - const globPattern = coreContractsOnly - ? `${BUILD_DIR}/contracts/@(${CoreContracts.join('|')}).json` - : `${BUILD_DIR}/contracts/*.json` - - exec(`yarn run --silent typechain --target=truffle --outDir "${outdir}" "${globPattern}"`) -} - -function generateFilesForEthers({ coreContractsOnly, ethersTypes: outdir }: BuildTargets) { - console.log(`protocol: Generating Ethers Types to ${outdir}`) - exec(`rm -rf "${outdir}"`) - - const contractKitContracts = coreContractsOnly - ? CoreContracts - : CoreContracts.concat('Proxy').concat(Interfaces) - const globPattern = `${BUILD_DIR}/contracts/@(${contractKitContracts.join('|')}).json` - - exec(`yarn run --silent typechain --target=ethers-v5 --outDir "${outdir}" "${globPattern}"`) -} - -async function generateFilesForContractKit({ coreContractsOnly, web3Types: outdir }: BuildTargets) { - console.log(`protocol: Generating Web3 Types to ${outdir}`) - exec(`rm -rf ${outdir}`) - const relativePath = path.relative(ROOT_DIR, outdir) - - const contractKitContracts = coreContractsOnly - ? CoreContracts - : CoreContracts.concat('Proxy').concat(Interfaces) - - const globPattern = `${BUILD_DIR}/contracts*/@(${contractKitContracts.join('|')}).json` - - const cwd = process.cwd() - - await tsGenerator( - { cwd, loggingLvl: 'info' }, - new Web3V1Celo({ - cwd, - rawConfig: { - files: globPattern, - outDir: relativePath, - }, - }) - ) - - for (const externalContractPackage of contractPackages) { - await tsGenerator( - { cwd, loggingLvl: 'info' }, - new Web3V1Celo({ - cwd, - rawConfig: { - files: `${BUILD_DIR}/contracts-${ - externalContractPackage.name - }/@(${externalContractPackage.contracts.join('|')}).json`, - outDir: path.join(relativePath, externalContractPackage.name), - }, - }) - ) - } - - exec(`yarn prettier --write "${outdir}/**/*.ts"`) -} - -const _buildTargets: ParsedArgs = { - _: [] as string[], - solidity: undefined, - truffleTypes: undefined, - web3Types: undefined, - ethersTypes: undefined, -} as const -type BuildTargets = Record & { - coreContractsOnly: boolean -} - -async function main(buildTargets: BuildTargets) { - if (buildTargets.solidity) { - compile(buildTargets) - } - if (buildTargets.truffleTypes) { - generateFilesForTruffle(buildTargets) - } - if (buildTargets.ethersTypes) { - generateFilesForEthers(buildTargets) - } - if (buildTargets.web3Types) { - await generateFilesForContractKit(buildTargets) - } -} - -const argv = minimist(process.argv.slice(2), { - string: Object.keys(_buildTargets), - boolean: ['coreContractsOnly'], -}) as unknown as BuildTargets - -main(argv).catch((err) => { - console.error(err) - process.exit(1) -}) diff --git a/packages/protocol/scripts/check-backward.ts b/packages/protocol/scripts/check-backward.ts deleted file mode 100644 index 311377fa9..000000000 --- a/packages/protocol/scripts/check-backward.ts +++ /dev/null @@ -1,120 +0,0 @@ -import { ASTContractVersionsChecker } from '@celo/protocol/lib/compatibility/ast-version' -import { DefaultCategorizer } from '@celo/protocol/lib/compatibility/categorizer' -import { ASTBackwardReport, instantiateArtifacts } from '@celo/protocol/lib/compatibility/utils' -import { writeJsonSync } from 'fs-extra' -import path from 'path' -import tmp from 'tmp' -import yargs from 'yargs' - -const COMMAND_REPORT = 'report' -const COMMAND_SEM_CHECK = 'sem_check' - -const argv = yargs - .command(COMMAND_REPORT, 'Generates a backward compatibility report') - .command( - COMMAND_SEM_CHECK, - 'Check if the semantic version change provided is correct (exit code 0, or 1 otherwise)' - ) - .option('exclude', { - alias: 'e', - description: 'Contract name exclusion regex', - type: 'string', - }) - .option('old_contracts', { - alias: 'o', - description: 'Old contracts build artifacts folder', - type: 'string', - demandOption: true, - }) - .option('new_contracts', { - alias: 'n', - description: 'New contracts build artifacts folder', - type: 'string', - demandOption: true, - }) - .option('output_file', { - alias: 'f', - description: 'Destination file output for the compatibility report', - type: 'string', - }) - .option('quiet', { - alias: 'q', - description: 'Run in quiet mode (no logs)', - default: false, - type: 'boolean', - }) - .help() - .alias('help', 'h') - .showHelpOnFail(true) - .demandCommand() - .strict().argv - -// old artifacts folder needs to be generalized https://github.com/celo-org/celo-monorepo/issues/10567 -const oldArtifactsFolder = path.relative(process.cwd(), argv.old_contracts) -const newArtifactsFolder = path.relative(process.cwd(), argv.new_contracts) -const newArtifactsFolder08 = path.relative(process.cwd(), argv.new_contracts + '-0.8') -const newArtifactsFolders = [newArtifactsFolder, newArtifactsFolder08] - -const out = (msg: string, force?: boolean): void => { - if (force || !argv.quiet) { - process.stdout.write(msg) - } -} - -const outFile = argv.output_file ? argv.output_file : tmp.tmpNameSync({}) -const exclude: RegExp = argv.exclude ? new RegExp(argv.exclude) : null -// old artifacts needs to be generalized https://github.com/celo-org/celo-monorepo/issues/10567 -const oldArtifacts = instantiateArtifacts(oldArtifactsFolder) -const newArtifacts = instantiateArtifacts(newArtifactsFolder) -const newArtifacts08 = instantiateArtifacts(newArtifactsFolder08) - -try { - const backward = ASTBackwardReport.create( - oldArtifactsFolder, - newArtifactsFolders, - oldArtifacts, - [newArtifacts, newArtifacts08], - exclude, - new DefaultCategorizer(), - out - ) - - out(`Writing compatibility report to ${outFile} ...`) - writeJsonSync(outFile, backward, { spaces: 2 }) - out('Done\n') - if (argv._.includes(COMMAND_REPORT)) { - // Report always generated - // Placebo command - } else if (argv._.includes(COMMAND_SEM_CHECK)) { - const doVersionCheck = async () => { - const versionChecker = await ASTContractVersionsChecker.create( - oldArtifacts, - [newArtifacts, newArtifacts08], - backward.report.versionDeltas() - ) - const mismatches = versionChecker.excluding(exclude).mismatches() - if (mismatches.isEmpty()) { - out('Success! Actual version numbers match expected\n') - process.exit(0) - } else { - console.error(`Version mismatch detected:\n${JSON.stringify(mismatches, null, 4)}`) - process.exit(1) - } - } - doVersionCheck().catch((err) => { - console.error('Error when performing version check', err) - process.exit(1) - }) - } else { - // Should never happen - console.error('Error parsing command line arguments') - process.exit(10007) - } -} catch (error) { - if (error.message) { - console.error(error.message) - } else { - console.error(error) - } - process.exit(10003) -} diff --git a/packages/protocol/scripts/check-opcodes.ts b/packages/protocol/scripts/check-opcodes.ts deleted file mode 100644 index e97e056f1..000000000 --- a/packages/protocol/scripts/check-opcodes.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { exec, ExecException } from 'child_process' -import path from 'path' -import { CoreContracts } from './consts' - -const UNSAFE_OPCODES = ['selfdestruct', 'delegatecall'] - -// ignore deprecated and known contracts -const IGNORE_CONTRACTS = ['ReleaseGold'] -const CHECK_CONTRACTS = CoreContracts.filter((c) => !IGNORE_CONTRACTS.includes(c)) - -const handleGrepOutput = (err: ExecException, grepOutput: string, stderr: string) => { - if (err || stderr) { - throw new Error('grep failed') - } - - const opcodeLines = grepOutput.toString().split('\n') - - let safe = true - opcodeLines.forEach((line) => { - const contractPath = line.split('.sol')[0] - const contractMatch = contractPath.slice(contractPath.lastIndexOf('/') + 1) - if (CHECK_CONTRACTS.includes(contractMatch)) { - safe = false - console.error(`Core contract ${contractMatch} should not include ${UNSAFE_OPCODES} opcodes`) - } - }) - - if (safe) { - // tslint:disable:no-console - console.log(`Core contracts are safe against ${UNSAFE_OPCODES} vulnerabilities`) - } else { - process.exit(1) - } -} - -const cmd = `egrep -r "(${UNSAFE_OPCODES.join('|')})\\(" ${path.join(__dirname, '../contracts')}` -exec(cmd, handleGrepOutput) diff --git a/packages/protocol/scripts/consts.ts b/packages/protocol/scripts/consts.ts deleted file mode 100644 index 45fb8aa45..000000000 --- a/packages/protocol/scripts/consts.ts +++ /dev/null @@ -1,102 +0,0 @@ -import path from 'path' -import { MENTO_PACKAGE, SOLIDITY_08_PACKAGE } from '../contractPackages' - -export const ROOT_DIR = path.join(__dirname, '../') -export const CONTRACTS_PACKAGE_SRC_DIR = path.join(__dirname, '../contracts') -export const CONTRACTS_08_SOURCE_DIR = path.join(ROOT_DIR, 'contracts-0.8') -export const CONTRACTS_08_PACKAGE_DESTINATION_DIR = path.join(CONTRACTS_PACKAGE_SRC_DIR, '0.8') -export const ABIS_PACKAGE_SRC_DIR = path.join(__dirname, '../abis') -export const ABIS_BUILD_DIR = path.join(ABIS_PACKAGE_SRC_DIR, 'src-generated') -export const ABIS_DIST_DIR = path.join(ABIS_PACKAGE_SRC_DIR, 'dist') -export const BUILD_EXECUTABLE = path.join(__dirname, 'build.ts') -export const TSCONFIG_PATH = path.join(ROOT_DIR, 'tsconfig.json') - -const PROXY_CONTRACT = 'Proxy' - -export const ProxyContracts = [ - 'AccountsProxy', - 'AttestationsProxy', - 'BlockchainParametersProxy', - 'DoubleSigningSlasherProxy', - 'DowntimeSlasherProxy', - 'ElectionProxy', - 'EpochRewardsProxy', - 'EscrowProxy', - 'FederatedAttestationsProxy', - 'FeeHandlerProxy', - 'MentoFeeHandlerSellerProxy', - 'FeeCurrencyWhitelistProxy', - 'GoldTokenProxy', - 'GovernanceApproverMultiSigProxy', - 'GovernanceProxy', - 'LockedGoldProxy', - 'MetaTransactionWalletProxy', - 'MetaTransactionWalletDeployerProxy', - 'OdisPaymentsProxy', - 'RegistryProxy', - 'SortedOraclesProxy', - 'UniswapFeeHandlerSellerProxy', -] - -export const CoreContracts = [ - // common - 'Accounts', - 'GasPriceMinimum', - 'FeeHandler', - 'MentoFeeHandlerSeller', - 'UniswapFeeHandlerSeller', - 'FeeCurrencyWhitelist', - 'GoldToken', - 'MetaTransactionWallet', - 'MetaTransactionWalletDeployer', - 'MultiSig', - 'Registry', - 'Freezer', - 'MetaTransactionWallet', - - // governance - 'Election', - 'EpochRewards', - 'Governance', - 'GovernanceApproverMultiSig', - 'BlockchainParameters', - 'DoubleSigningSlasher', - 'DowntimeSlasher', - 'LockedGold', - 'Validators', - 'ReleaseGold', - - // identity - 'Attestations', - 'Escrow', - 'FederatedAttestations', - 'Random', - 'OdisPayments', - - // stability - 'SortedOracles', -] - -export const OtherContracts = [ - PROXY_CONTRACT, - 'Migrations', - // abstract - 'Initializable', - 'UsingRegistry', -] - -export const contractPackages = [MENTO_PACKAGE, SOLIDITY_08_PACKAGE].filter(Boolean) - -export const Interfaces = ['ICeloToken', 'IERC20', 'ICeloVersionedContract'] - -export const ImplContracts = OtherContracts.concat(ProxyContracts).concat(CoreContracts) - -export const PublishContracts = CoreContracts.concat(Interfaces) - .concat(PROXY_CONTRACT) - .concat(MENTO_PACKAGE.contracts) - -export enum BuildTarget { - CJS = 'cjs', - ESM = 'esm', - TYPES = 'types', -} diff --git a/packages/protocol/scripts/devchain.ts b/packages/protocol/scripts/devchain.ts deleted file mode 100644 index 6e07d0639..000000000 --- a/packages/protocol/scripts/devchain.ts +++ /dev/null @@ -1,410 +0,0 @@ -import chalk from 'chalk' -import { spawn, SpawnOptions } from 'child_process' -import fs from 'fs-extra' -import ganache from 'ganache' -import path from 'path' -import targz from 'targz' -import tmp from 'tmp' -import yargs from 'yargs' - -tmp.setGracefulCleanup() - -const MNEMONIC = 'concert load couple harbor equip island argue ramp clarify fence smart topic' - -const gasLimit = 20000000 - -const ProtocolRoot = path.normalize(path.join(__dirname, '../')) - -// As documented https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables -const isCI = process.env.CI === 'true' - -// Move to where the caller made the call So to have relative paths -const CallerCWD = process.env.INIT_CWD ? process.env.INIT_CWD : process.cwd() -process.chdir(CallerCWD) - -// tslint:disable-next-line: no-unused-expression -yargs - .scriptName('devchain') - .recommendCommands() - .demandCommand(1) - .strict(true) - .showHelpOnFail(true) - .command( - 'run ', - "Run celo's devchain using given datadir without copying it", - (args) => - args - .positional('datadir', { type: 'string', description: 'Data Dir' }) - .option('reset', { - type: 'boolean', - description: 'Start fresh if enabled', - }) - .option('upto', { - type: 'number', - description: 'When reset, run upto given migration', - }), - (args) => - exitOnError(runDevChain(args.datadir, { reset: args.reset, upto: args.upto, targz: false })) - ) - .command( - 'run-tar ', - "Run celo's devchain using given tar filename. Generates a copy and then delete it", - (args) => args.positional('filename', { type: 'string', description: 'Chain tar filename' }), - (args) => exitOnError(runDevChainFromTar(args.filename)) - ) - .command( - 'run-tar-in-bg ', - "Run celo's devchain using given tar filename. Generates a copy and then delete it", - (args) => args.positional('filename', { type: 'string', description: 'Chain tar filename' }), - (args) => exitOnError(runDevChainFromTarInBackGround(args.filename)) - ) - .command( - 'generate ', - 'Create a new devchain directory from scratch', - (args) => - args - .positional('datadir', { type: 'string', description: 'Data Dir' }) - .option('upto', { - type: 'number', - description: 'When reset, run upto given migration', - }) - .option('migration_override', { - type: 'string', - description: 'Path to JSON containing config values to use in migrations', - }), - (args) => - exitOnError( - generateDevChain(args.datadir, { - upto: args.upto, - migrationOverride: args.migration_override, - targz: false, - }) - ) - ) - .command( - 'generate-tar ', - 'Create a new devchain.tar.gz from scratch', - (args) => - args - .positional('filename', { type: 'string', description: 'chain tar filename' }) - .option('upto', { - type: 'number', - description: 'When reset, run upto given migration', - }) - .option('migration_override', { - type: 'string', - description: 'Path to JSON containing config values to use in migrations', - }) - .option('release_gold_contracts', { - type: 'string', - description: 'Path to JSON containing list of release gold contracts', - }), - (args) => - exitOnError( - generateDevChain(args.filename, { - upto: args.upto, - migrationOverride: args.migration_override, - releaseGoldContracts: args.release_gold_contracts, - targz: true, - }) - ) - ) - .command( - 'compress-chain ', - 'Create a devchain.tar.gz from specified datadir', - (args) => - args - .positional('datadir', { type: 'string', description: 'datadir path' }) - .positional('filename', { type: 'string', description: 'chain tar filename' }), - (args) => exitOnError(compressChain(args.datadir, args.filename)) - ).argv - -async function startGanache( - datadir: string, - opts: { verbose?: boolean }, - chainCopy?: tmp.DirResult -) { - const logFn = opts.verbose - ? // tslint:disable-next-line: no-console - (...args: any[]) => console.log(...args) - : () => { - /*nothing*/ - } - - const server = ganache.server({ - logging: { logger: { log: logFn } }, - database: { dbPath: datadir }, - wallet: { mnemonic: MNEMONIC, defaultBalance: 200000000 }, - miner: { blockGasLimit: gasLimit }, - chain: { networkId: 1101, chainId: 1, allowUnlimitedContractSize: true }, - allowUnlimitedInitCodeSize: true, - }) - - server.listen(8545, async (err) => { - if (err) { - throw err - } - // tslint:disable-next-line: no-console - console.log(chalk.red('Ganache STARTED')) - }) - - return async () => { - try { - await server.close() - if (chainCopy) { - chainCopy.removeCallback() - } - // tslint:disable-next-line: no-console - console.log(chalk.red('Ganache server CLOSED')) - } catch (e) { - throw e - } - } -} - -export function execCmd( - cmd: string, - args: string[], - options?: SpawnOptions & { silent?: boolean } -) { - return new Promise(async (resolve, reject) => { - const { silent, ...spawnOptions } = options || { silent: false } - if (!silent) { - console.debug('$ ' + [cmd].concat(args).join(' ')) - } - const process = spawn(cmd, args, { - ...spawnOptions, - stdio: silent ? 'ignore' : 'inherit', - }) - process.on('close', (code) => { - try { - resolve(code) - } catch (error) { - reject(error) - } - }) - }) -} - -function exitOnError(p: Promise) { - p.catch((err) => { - console.error(`Command Failed`) - console.error(err) - process.exit(1) - }) -} - -async function resetDir(dir: string, silent?: boolean) { - if (fs.existsSync(dir)) { - await execCmd('rm', ['-rf', dir], { silent }) - } -} -function createDirIfMissing(dir: string) { - if (!fs.existsSync(dir)) { - fs.mkdirSync(dir) - } -} - -function runMigrations(opts: { upto?: number; migrationOverride?: string } = {}) { - const cmdArgs = ['truffle', 'migrate', '--reset', '--network', 'development'] - - if (opts.upto) { - cmdArgs.push('--to') - cmdArgs.push(opts.upto.toString()) - } - - if (opts.migrationOverride) { - cmdArgs.push('--migration_override') - cmdArgs.push(fs.readFileSync(opts.migrationOverride).toString()) - } - return execCmd(`yarn`, cmdArgs, { cwd: ProtocolRoot }) -} - -function deployReleaseGold(releaseGoldContracts: string) { - const cmdArgs = ['truffle', 'exec', 'scripts/truffle/deploy_release_contracts.js'] - cmdArgs.push('--network') - // TODO(lucas): investigate if this can be found dynamically - cmdArgs.push('development') - cmdArgs.push('--from') - cmdArgs.push('0x5409ED021D9299bf6814279A6A1411A7e866A631') - cmdArgs.push('--grants') - cmdArgs.push(releaseGoldContracts) - cmdArgs.push('--start_gold') - cmdArgs.push('1') - cmdArgs.push('--deployed_grants') - // Random file name to prevent rewriting to it - cmdArgs.push('/tmp/deployedGrants' + Math.floor(1000 * Math.random()) + '.json') - cmdArgs.push('--output_file') - cmdArgs.push('/tmp/releaseGoldOutput.txt') - // --yesreally command to bypass prompts - cmdArgs.push('--yesreally') - cmdArgs.push('--build_directory') - cmdArgs.push(ProtocolRoot + 'build') - - return execCmd(`yarn`, cmdArgs, { cwd: ProtocolRoot }) -} - -async function runDevChainFromTar(filename: string) { - const chainCopy: tmp.DirResult = tmp.dirSync({ keep: false, unsafeCleanup: true }) - // tslint:disable-next-line: no-console - console.log(`Creating tmp folder: ${chainCopy.name}`) - - await decompressChain(filename, chainCopy.name) - - console.info('Starting Ganache ...') - const stopGanache = await startGanache(chainCopy.name, { verbose: true }, chainCopy) - if (isCI) { - // If we are running on circle ci we need to wait for ganache to be up. - await waitForPortOpen('localhost', 8545, 120) - } - - return stopGanache -} - -/// This function was created to replace `startInBgAndWaitForString` in `release-on-devchain.sh` -/// and intended to be run on a hosted instances that shutdown after execution. -/// Note: If you run this locally, you will need to properly cleanup tmp.DirResult and -/// manually close the detached ganache instance. -/// see https://trufflesuite.com/docs/ganache/reference/cli-options/#manage-detached-instances for more details -async function runDevChainFromTarInBackGround(filename: string) { - const cmdArgs = ['ganache-devchain', '-d'] - - // keep is set to true, because `release-on-devchain` fails when set to false. - const chainCopy: tmp.DirResult = tmp.dirSync({ keep: true, unsafeCleanup: true }) - - // tslint:disable-next-line: no-console - console.log(`Creating tmp folder: ${chainCopy.name}`) - - await decompressChain(filename, chainCopy.name) - - cmdArgs.push(chainCopy.name) - - return execCmd(`yarn`, cmdArgs, { cwd: ProtocolRoot }) -} - -function decompressChain(tarPath: string, copyChainPath: string): Promise { - // tslint:disable-next-line: no-console - console.log('Decompressing chain') - return new Promise((resolve, reject) => { - targz.decompress({ src: tarPath, dest: copyChainPath }, (err) => { - if (err) { - console.error(err) - reject(err) - } else { - // tslint:disable-next-line: no-console - console.log('Chain decompressed') - resolve() - } - }) - }) -} - -async function runDevChain( - datadir: string, - opts: { - reset?: boolean - upto?: number - migrationOverride?: string - targz?: boolean - runMigrations?: boolean - releaseGoldContracts?: string - } = {} -) { - if (opts.reset) { - await resetDir(datadir) - } - createDirIfMissing(datadir) - console.info('Starting Ganache ...') - const stopGanache = await startGanache(datadir, { verbose: true }) - if (isCI) { - // If we are running on circle ci we need to wait for ganache to be up. - await waitForPortOpen('localhost', 8545, 120) - } - if (opts.reset || opts.runMigrations) { - const code = await runMigrations({ upto: opts.upto, migrationOverride: opts.migrationOverride }) - if (code !== 0) { - throw Error('Migrations failed') - } - console.info('Migrations successfully applied') - } - if (opts.releaseGoldContracts) { - const code = await deployReleaseGold(opts.releaseGoldContracts) - if (code !== 0) { - throw Error('ReleaseGold deployment failed') - } - console.info('ReleaseGold successfully deployed') - } - return stopGanache -} - -async function generateDevChain( - filePath: string, - opts: { - upto?: number - migrationOverride?: string - releaseGoldContracts?: string - targz?: boolean - } = {} -) { - let chainPath = filePath - let chainTmp: tmp.DirResult - if (opts.targz) { - chainTmp = tmp.dirSync({ keep: false, unsafeCleanup: true }) - chainPath = chainTmp.name - } else { - fs.ensureDirSync(chainPath) - } - const stopGanache = await runDevChain(chainPath, { - reset: !opts.targz, - runMigrations: true, - upto: opts.upto, - migrationOverride: opts.migrationOverride, - releaseGoldContracts: opts.releaseGoldContracts, - }) - await stopGanache() - if (opts.targz && chainTmp) { - await compressChain(chainPath, filePath) - chainTmp.removeCallback() - } -} - -async function compressChain(chainPath: string, filename: string): Promise { - // tslint:disable-next-line: no-console - console.log('Compressing chain') - return new Promise((resolve, reject) => { - // ensures the path to the file - fs.ensureFileSync(filename) - targz.compress({ src: chainPath, dest: filename }, async (err: Error) => { - if (err) { - console.error(err) - reject(err) - } else { - // tslint:disable-next-line: no-console - console.log('Chain compressed') - resolve() - } - }) - }) -} - -export async function waitForPortOpen(host: string, port: number, seconds: number) { - console.info(`Waiting for ${host}:${port} to open for ${seconds}s`) - const deadline = Date.now() + seconds * 1000 - do { - if (await isPortOpen(host, port)) { - await delay(10000) // extra 10s just to give ganache extra time to startup - console.info(`Port ${host}:${port} opened`) - return true - } - } while (Date.now() < deadline) - console.info('Port was not opened in time') - return false -} - -async function isPortOpen(host: string, port: number) { - return (await execCmd('nc', ['-z', host, port.toString()], { silent: true })) === 0 -} - -function delay(time) { - return new Promise((resolve) => setTimeout(resolve, time)) -} diff --git a/packages/protocol/scripts/is-contract-release.ts b/packages/protocol/scripts/is-contract-release.ts deleted file mode 100644 index b7decefcc..000000000 --- a/packages/protocol/scripts/is-contract-release.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { SemVer } from 'semver' -const arg = process.env.INPUT_VERSION || process.env.GITHUB_TAG - -const match = arg?.match(/core-contracts.v(.+)/) -if (!match) { - console.error( - `Git tag didn't match the following RegExp("/core-contracts.v(.+)/"), got ${arg}, next steps will be dry-run.` - ) - process.exit(0) -} - -const [, gitTag] = match -const [major, minor, ...patchAndMore] = gitTag.split('.') -const semver = new SemVer( - [major, minor || 0, ...(patchAndMore.length ? patchAndMore : [0])].map((x) => x || 0).join('.') -) - -// tslint:disable-next-line -console.log(`RELEASE_VERSION=${semver.version}`) -// tslint:disable-next-line -console.log(`RELEASE_TYPE=${semver.prerelease.length ? semver.prerelease[0] : 'latest'}`) -process.exit(0) diff --git a/packages/protocol/scripts/make-release-3-changes.ts b/packages/protocol/scripts/make-release-3-changes.ts deleted file mode 100644 index 4fcf79255..000000000 --- a/packages/protocol/scripts/make-release-3-changes.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { ensureLeading0x, trimLeading0x } from '@celo/base' -import { readJsonSync, writeJsonSync } from 'fs-extra' -import { - getProposedProxyAddress, - isProxyRepointAndInitForIdTransaction, -} from '../lib/compatibility/verify-bytecode' -import { ProposalTx } from './truffle/make-release' - -const makeRelease3Changes = (releaseProposal: ProposalTx[]) => { - const stableTokenEURaddr = getProposedProxyAddress('StableTokenEUR', releaseProposal) - const exchangeInitIndex = releaseProposal.findIndex((tx) => - isProxyRepointAndInitForIdTransaction(tx, 'ExchangeEURProxy') - ) - const initCallData = trimLeading0x(releaseProposal[exchangeInitIndex].args[1]) - const paramPosition = (4 + 32) * 2 // (functionSelector + 1 parameter) * 2 hex - releaseProposal[exchangeInitIndex].args[1] = ensureLeading0x( - initCallData.slice(0, paramPosition) + - trimLeading0x(stableTokenEURaddr).padStart(64, '0') + - initCallData.slice(paramPosition + 32 * 2) // offset 1 parameter * 2 hex - ) - return releaseProposal -} - -try { - const argv = require('minimist')(process.argv.slice(2), { - string: ['input_proposal', 'output_proposal'], - }) - const releaseProposal: ProposalTx[] = readJsonSync(argv.input_proposal) - writeJsonSync(argv.output_proposal, makeRelease3Changes(releaseProposal), { spaces: 2 }) - // tslint:disable-next-line: no-console - console.log(`Modifications made sucessfully; written to ${argv.output_proposal}`) -} catch (e) { - // tslint:disable-next-line: no-console - console.error(`Something went wrong: ${e}`) -} diff --git a/packages/protocol/scripts/make-release-6-changes.ts b/packages/protocol/scripts/make-release-6-changes.ts deleted file mode 100644 index d5b2c0bbf..000000000 --- a/packages/protocol/scripts/make-release-6-changes.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { ensureLeading0x, trimLeading0x } from '@celo/base' -import { readJsonSync, writeJsonSync } from 'fs-extra' -import { - getProposedProxyAddress, - isProxyRepointAndInitForIdTransaction, -} from '../lib/compatibility/verify-bytecode' -import { ProposalTx } from './truffle/make-release' - -const makeRelease6Changes = (releaseProposal: ProposalTx[]) => { - const stableTokenBRLaddr = getProposedProxyAddress('StableTokenBRL', releaseProposal) - const exchangeInitIndex = releaseProposal.findIndex((tx) => - isProxyRepointAndInitForIdTransaction(tx, 'ExchangeBRLProxy') - ) - const initCallData = trimLeading0x(releaseProposal[exchangeInitIndex].args[1]) - const paramPosition = (4 + 32) * 2 // (functionSelector + 1 parameter) * 2 hex - releaseProposal[exchangeInitIndex].args[1] = ensureLeading0x( - initCallData.slice(0, paramPosition) + - trimLeading0x(stableTokenBRLaddr).padStart(64, '0') + - initCallData.slice(paramPosition + 32 * 2) // offset 1 parameter * 2 hex - ) - return releaseProposal -} - -try { - const argv = require('minimist')(process.argv.slice(2), { - string: ['input_proposal', 'output_proposal'], - }) - const releaseProposal: ProposalTx[] = readJsonSync(argv.input_proposal) - writeJsonSync(argv.output_proposal, makeRelease6Changes(releaseProposal), { spaces: 2 }) - // tslint:disable-next-line: no-console - console.log(`Modifications made sucessfully; written to ${argv.output_proposal}`) -} catch (e) { - // tslint:disable-next-line: no-console - console.error(`Something went wrong: ${e}`) -} diff --git a/packages/protocol/scripts/prepare-contracts-and-abis-publishing.ts b/packages/protocol/scripts/prepare-contracts-and-abis-publishing.ts deleted file mode 100644 index 25b298c4a..000000000 --- a/packages/protocol/scripts/prepare-contracts-and-abis-publishing.ts +++ /dev/null @@ -1,302 +0,0 @@ -import * as child_process from 'child_process' -import * as fs from 'fs' -import * as path from 'path' -import { sync as rmrfSync } from 'rimraf' -import { MENTO_PACKAGE, SOLIDITY_08_PACKAGE } from '../contractPackages' -import { - ABIS_BUILD_DIR, - ABIS_DIST_DIR, - ABIS_PACKAGE_SRC_DIR, - BUILD_EXECUTABLE, - BuildTarget, - CONTRACTS_08_PACKAGE_DESTINATION_DIR, - CONTRACTS_08_SOURCE_DIR, - CONTRACTS_PACKAGE_SRC_DIR, - PublishContracts, - TSCONFIG_PATH, -} from './consts' - -function log(...args: any[]) { - // tslint:disable-next-line - console.log('[prepare-contracts-and-abis]', ...args) -} - -try { - log('Setting package.json target to ES2020') - const tsconfig = JSON.parse(fs.readFileSync(TSCONFIG_PATH, 'utf8')) - tsconfig.compilerOptions.target = 'ES2020' - fs.writeFileSync(TSCONFIG_PATH, JSON.stringify(tsconfig, null, 4)) - - // Start from scratch - rmrfSync([ABIS_BUILD_DIR, ABIS_DIST_DIR, CONTRACTS_08_PACKAGE_DESTINATION_DIR]) - fs.mkdirSync(ABIS_BUILD_DIR, { recursive: true }) - fs.mkdirSync(ABIS_DIST_DIR, { recursive: true }) - - // Generate all ABIs - build(`--solidity ${path.join(ABIS_BUILD_DIR)}`) - - // Generate web3 typings - build(`--web3Types ${path.join(ABIS_BUILD_DIR, 'web3')}`) - - // Merge contracts-0.8, contracts-mento, etc.. at the root of the build dir - log('Merging files at the root of the build dir') - mergeFromFolder( - ['contracts', `contracts-${MENTO_PACKAGE.name}`, `contracts-${SOLIDITY_08_PACKAGE.name}`], - path.join(ABIS_BUILD_DIR) - ) - - // Remove Mocks, tests, extraneous files - log('Deleting extraneous files') - const allFiles = lsRecursive(ABIS_BUILD_DIR) - allFiles.forEach((filePath) => { - const name = path.basename(filePath) - const baseName = name.replace(/.(sol|d.ts|json)$/, '') - - if (baseName !== 'index' && !PublishContracts.includes(baseName)) { - rmrfSync(path.join(ABIS_BUILD_DIR, `${baseName}.json`)) - rmrfSync(path.join(ABIS_BUILD_DIR, `${baseName}.ts`)) - rmrfSync(path.join(ABIS_BUILD_DIR, '**', `${baseName}.d.ts`)) - rmrfSync(path.join(ABIS_BUILD_DIR, '**', `${baseName}.ts`)) - } - }) - - let exports = processRawJsonsAndPrepareExports() - - // Generate ts abi files - log('Running yarn wagmi generate') - child_process.execSync(`yarn wagmi generate`, { stdio: 'inherit' }) - - // must be after wagmi gen but before compiling - createIndex() - - log('Compiling esm') - child_process.execSync(`yarn tsc -b ${path.join(ABIS_PACKAGE_SRC_DIR, 'tsconfig-esm.json')}`, { - stdio: 'inherit', - }) - - log('Compiling cjs') - child_process.execSync(`yarn tsc -b ${path.join(ABIS_PACKAGE_SRC_DIR, 'tsconfig-cjs.json')}`, { - stdio: 'inherit', - }) - - log('Compiling declarations') - child_process.execSync(`yarn tsc -b ${path.join(ABIS_PACKAGE_SRC_DIR, 'tsconfig-types.json')}`, { - stdio: 'inherit', - }) - - exports = { - '.': { - import: './dist/esm/index.js', - require: './dist/cjs/index.js', - types: './dist/types/index.d.ts', - }, - ...exports, - ...prepareTargetTypesExports(), - } - - // Change the packages version to what CI is providing from environment variables - prepareAbisPackageJson(exports) - prepareContractsPackage() -} finally { - // Cleanup - log('Cleaning up folders and checking out dirty git files') - rmrfSync(`rm -rf ${ABIS_BUILD_DIR}/contracts*`) - rmrfSync(`rm -rf ${ABIS_BUILD_DIR}/truffle*`) - child_process.execSync(`git checkout ${TSCONFIG_PATH}`, { stdio: 'inherit' }) -} - -function createIndex() { - const reExports = PublishContracts.map((contractName) => { - return `export * from './${contractName}.js'` - }) - - fs.writeFileSync(path.join(ABIS_BUILD_DIR, 'index.ts'), reExports.join('\n')) -} - -// Helper functions -function prepareTargetTypesExports() { - const exports = {} - const targets = [BuildTarget.ESM, BuildTarget.CJS, BuildTarget.TYPES] - - targets.forEach((target) => { - // We don't need package.json for type declarations - if (target !== BuildTarget.TYPES) { - fs.copyFileSync( - path.join(ABIS_PACKAGE_SRC_DIR, `package-${target}.json`), - path.join(ABIS_DIST_DIR, target, 'package.json') - ) - } - - const filePaths = lsRecursive(path.join(ABIS_DIST_DIR, target)) - filePaths.forEach((filePath) => { - const parsedPath = path.parse(filePath) - - // Remove the .d from the name -- only for types types no harm otherwise - const parsedPathName = parsedPath.name.replace('.d', '') - if (PublishContracts.includes(parsedPathName)) { - const relativePath = path.join( - path.relative(ABIS_PACKAGE_SRC_DIR, parsedPath.dir), - parsedPathName - ) - const exportKey = `./${path.join( - path.relative(path.join(ABIS_DIST_DIR, target), parsedPath.dir), - parsedPathName - )}` - - if (!exports.hasOwnProperty(exportKey)) { - exports[exportKey] = {} - } - - if (target === BuildTarget.ESM) { - const importPath = `./${relativePath}.js` - - expectFileExists(importPath) - - exports[exportKey] = { - ...exports[exportKey], - import: importPath, - } - } else if (target === BuildTarget.CJS) { - const requirePath = `./${relativePath}.js` - - expectFileExists(requirePath) - - exports[exportKey] = { - ...exports[exportKey], - require: requirePath, - } - } else { - // types - const typesPath = `./${relativePath}.d.ts` - - expectFileExists(typesPath) - - exports[exportKey] = { - ...exports[exportKey], - types: typesPath, - } - } - } - }) - }) - - return exports -} - -function expectFileExists(relativePath: string) { - if (!fs.existsSync(path.join(ABIS_PACKAGE_SRC_DIR, relativePath))) { - throw new Error(`Expected file ${relativePath} to exist`) - } -} - -function processRawJsonsAndPrepareExports() { - const exports = {} - - log('Removing extraneous fields from generated json files') - const fileNames = fs.readdirSync(ABIS_BUILD_DIR) - - fileNames.forEach((fileName) => { - const filePath = path.join(ABIS_BUILD_DIR, fileName) - const parsedPath = path.parse(filePath) - - if (PublishContracts.includes(parsedPath.name)) { - const json = JSON.parse(fs.readFileSync(filePath).toString()) - const defaultPath = path.join( - path.relative(ABIS_PACKAGE_SRC_DIR, ABIS_DIST_DIR), - `${parsedPath.name}.json` - ) - - fs.writeFileSync( - path.join(ABIS_DIST_DIR, fileName), - JSON.stringify( - { - contractName: json.contractName, - abi: json.abi, - }, - null, - 2 - ) - ) - - expectFileExists(defaultPath) - - exports[`./${parsedPath.name}.json`] = { - default: `./${defaultPath}`, - } - } - }) - - return exports -} - -function prepareAbisPackageJson(exports) { - log('Preparing @celo/abis package.json') - const packageJsonPath = path.join(ABIS_PACKAGE_SRC_DIR, 'package.json') - const json = JSON.parse(fs.readFileSync(packageJsonPath).toString()) - - if (process.env.RELEASE_VERSION) { - log('Replacing @celo/abis version with provided RELEASE_VERSION') - - json.version = process.env.RELEASE_VERSION - } else { - log('No RELEASE_VERSION provided') - } - - log('Setting @celo/abis exports') - json.exports = exports - - fs.writeFileSync(packageJsonPath, JSON.stringify(json, null, 2)) -} - -function prepareContractsPackage() { - const contracts08CpCommand = `cp -r ${CONTRACTS_08_SOURCE_DIR} ${CONTRACTS_08_PACKAGE_DESTINATION_DIR}` - log(contracts08CpCommand) - child_process.execSync(contracts08CpCommand) - - if (process.env.RELEASE_VERSION) { - log('Replacing @celo/contracts version with RELEASE_VERSION)') - const contractsPackageJsonPath = path.join(CONTRACTS_PACKAGE_SRC_DIR, 'package.json') - const contents = fs.readFileSync(contractsPackageJsonPath).toString() - - fs.writeFileSync( - contractsPackageJsonPath, - contents.replace('0.0.0-template.version', process.env.RELEASE_VERSION) - ) - - return - } - - log('Skipping @celo/contracts package.json preparation (no RELEASE_VERSION provided)') -} - -function lsRecursive(dir: string): string[] { - const filesAndDirectories = fs.readdirSync(dir, { withFileTypes: true }) - return filesAndDirectories.reduce((fileNames, fileOrDir) => { - const filePath = path.join(dir, fileOrDir.name) - if (fileOrDir.isDirectory()) { - return fileNames.concat(lsRecursive(filePath)) - } - return fileNames.concat(...[filePath]) - }, [] as string[]) -} - -function build(cmd: string) { - log(`Running build for ${cmd}`) - child_process.execSync(`BUILD_DIR=./build ts-node ${BUILD_EXECUTABLE} ${cmd}`, { - stdio: 'inherit', - }) -} - -function mergeFromFolder(folderNames: string[], rootFolderName: string) { - for (const folderName of folderNames) { - const mvCommand = `mv -f ${rootFolderName}/${folderName}/* ${rootFolderName}` - const rmCommand = `rm -r ${rootFolderName}/${folderName}` - - log(mvCommand) - child_process.execSync(mvCommand) - - // Once copied all the files, remove the folder - log(rmCommand) - child_process.execSync(rmCommand) - } -} diff --git a/packages/protocol/scripts/sourcify-publish.ts b/packages/protocol/scripts/sourcify-publish.ts deleted file mode 100644 index bab30e095..000000000 --- a/packages/protocol/scripts/sourcify-publish.ts +++ /dev/null @@ -1,114 +0,0 @@ -/* tslint:disable no-console */ -import FormData from 'form-data' -import fs from 'fs' -import fetch from 'node-fetch' -import path from 'path' -import Web3 from 'web3' - -/* - * A script that reads the artifacts from the build/contracts directory and publish using the sourcify api. - * - * NOTE: this script hasn't been tested yet. It should be manually tested and - * potentially adjusted before including it in the release process. - * - * Expects the following flags: - * network: The network for which artifacts should be - * build_artifacts_path: Path containing the artifacts to publish - * proposal_path: Path to the proposal file - * - * Run using yarn run sourcify-publish, e.g.: - * yarn run sourcify-publish \ - * --network alfajores --build_artifacts_path ./build/contracts --proposal_path ./proposal.json - * - * report.json is generated by the build script with this format: - * [{ - * "contract": "Proxy", - * "function": "_setImplementation", - * "args": "[]", - * },{ - * "contract": "Registry", - * "function": "setAddressFor", - * "args": ["", ""] - * }] - * - */ - -interface BuildOptions { - network: string - buildArtifactsPath: string - proposalPath: string -} - -async function main(buildTargets: BuildOptions) { - const artifactBasePath = buildTargets.buildArtifactsPath || './build/contracts' - const artifactPaths = fs.readdirSync(artifactBasePath) - const reportPath = buildTargets.proposalPath || './proposal.json' - const report = require(path.join(process.cwd(), reportPath)) - const network = buildTargets.network - const web3 = new Web3('http://localhost:8545') - const chainId = await web3.eth.getChainId() - - console.log('Uploading sources & metadata') - console.log('============================') - console.log(artifactPaths) - - const artifacts = artifactPaths.map((a) => require(path.join(process.cwd(), artifactBasePath, a))) - - if ( - !isEqual( - artifacts.map((a) => a.contractName), - report.map((a) => a.contract) - ) - ) { - if (report.length !== artifactPaths.length) { - throw new Error( - `There are ${report.length} addresses to publish, but there are ${artifactPaths.length} artifacts.` - ) - } else { - throw new Error(`Contracts names are not equal`) - } - } - - for (const r of report) { - const artifact = artifacts.find((a) => a.contractName === r.contract) - - console.log() - console.log(artifact.contractName) - console.log('-'.repeat(artifact.contractName.length)) - - const address = r.contract.includes('Proxy') ? r.args[0] : r.args[1] - const formData = new FormData() - formData.append( - 'files', - fs.createReadStream(artifactBasePath + '/' + artifact.contractName + '.json') - ) - formData.append('address', address) - formData.append('chain', chainId) - - await fetch('https://sourcify.dev/server', { - method: 'POST', - body: formData, - }) - .then((res) => res.json()) - .then((json) => - fetch( - `https://${network}-blockscout.celo-testnet.org/address/${json.result[0].address}/contracts` - ) - ) - } - console.log('Finished.') -} - -const isEqual = (a, b) => JSON.stringify(a) === JSON.stringify(b) - -const minimist = require('minimist') -const argv = minimist(process.argv.slice(3), { - string: ['network', 'build_artifacts_path', 'proposal_path'], -}) - -main(argv) - .then(() => process.exit(0)) - .catch((err) => { - console.log(err) - process.exit(1) - }) diff --git a/packages/protocol/scripts/truffle/deploy_multisig.ts b/packages/protocol/scripts/truffle/deploy_multisig.ts deleted file mode 100644 index 6c8824a98..000000000 --- a/packages/protocol/scripts/truffle/deploy_multisig.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { _setInitialProxyImplementation, retryTx } from '@celo/protocol/lib/web3-utils' -import { MultiSigContract, ProxyContract } from 'types' - -/* - * A simple script to deploy a multisig contract. - * - * Expects the following flags: - * from: address of the account to making the request (should be unlocked for the running fullnode) - * owners: comma delimited list of multisig owners - * required: number of required owners needed to execute a call - * internalRequired: number of required owners needed to make internal changes to the multisig (eg. adding/removing owners) - * network: name of the network defined in truffle-config.js to deploy to - * - * Run using truffle exec, e.g.: - * yarn run truffle exec ./scripts/truffle/deploy_multisig.js --from 0xdead --owners 0xdead,0xf00d,0xd8a3 --required 2 --internalRequired 2 --network rc1 - * - */ -module.exports = async (callback: (error?: any) => number) => { - try { - const argv = require('minimist')(process.argv.slice(4), { - string: ['from', 'owners', 'required', 'internalRequired'], - }) - const multSig: MultiSigContract = artifacts.require('MultiSig') - const Proxy: ProxyContract = artifacts.require('Proxy') - - console.info(' Deploying MultiSigProxy...') - const proxy = await retryTx(Proxy.new, [{ from: argv.from }]) - console.info(' Deploying MultiSig...') - const multiSig = await retryTx(multSig.new, [{ from: argv.from }]) - await _setInitialProxyImplementation( - web3, - multiSig, - proxy, - 'MultiSig', - { - from: argv.from, - value: null, - }, - argv.owners.split(','), - argv.required, - argv.internalRequired - ) - await retryTx(proxy._transferOwnership, [ - proxy.address, - { - from: argv.from, - }, - ]) - console.info('Proxy address', proxy.address) - console.info('Implementation address', multiSig.address) - callback() - } catch (e) { - console.error('Something went wrong') - callback(e) - } -} diff --git a/packages/protocol/scripts/truffle/deploy_release_contracts.ts b/packages/protocol/scripts/truffle/deploy_release_contracts.ts deleted file mode 100644 index 08ab653b3..000000000 --- a/packages/protocol/scripts/truffle/deploy_release_contracts.ts +++ /dev/null @@ -1,665 +0,0 @@ -import { celoRegistryAddress } from '@celo/protocol/lib/registry-utils' -import { _setInitialProxyImplementation, retryTx } from '@celo/protocol/lib/web3-utils' -import { Address, isValidAddress } from '@celo/utils/lib/address' -import BigNumber from 'bignumber.js' -import chalk from 'chalk' -import fs from 'fs' -import prompts from 'prompts' -import { - ReleaseGoldContract, - ReleaseGoldMultiSigContract, - ReleaseGoldMultiSigProxyContract, - ReleaseGoldProxyContract, -} from 'types' - -let argv: any -let releases: any -let startGold: any -let fromAddress: any -let deployedGrants: any -let deployedGrantsFile: string -let ReleaseGoldMultiSig: ReleaseGoldMultiSigContract -let ReleaseGoldMultiSigProxy: ReleaseGoldMultiSigProxyContract -let ReleaseGold: ReleaseGoldContract -let ReleaseGoldProxy: ReleaseGoldProxyContract -const ONE_CELO = web3.utils.toWei('1', 'ether') -const TWO_CELO = web3.utils.toWei('2', 'ether') -const MAINNET_START_TIME = new Date('22 April 2020 16:00:00 UTC').getTime() / 1000 -const ZERO_ADDRESS: Address = '0x0000000000000000000000000000000000000000' - -interface ReleaseGoldConfig { - identifier: string - releaseStartTime: string - releaseCliffTime: number - numReleasePeriods: number - releasePeriod: number - amountReleasedPerPeriod: number - revocable: boolean - beneficiary: Address - releaseOwner: Address - refundAddress: Address - subjectToLiquidityProvision: boolean - initialDistributionRatio: number - canValidate: boolean - canVote: boolean -} - -type ReleaseGoldTemplate = Partial - -async function handleGrant(config: ReleaseGoldConfig, currGrant: number) { - console.info('Processing grant number ' + currGrant) - - // Sentinel MAINNET dictates a start time of mainnet launch, April 22 2020 16:00 UTC in this case - const releaseStartTime = config.releaseStartTime.startsWith('MAINNET') - ? MAINNET_START_TIME - : new Date(config.releaseStartTime).getTime() / 1000 - - const weiAmountReleasedPerPeriod = new BigNumber( - web3.utils.toWei(config.amountReleasedPerPeriod.toString()) - ) - - let totalValue = weiAmountReleasedPerPeriod.multipliedBy(config.numReleasePeriods) - if (totalValue.lt(startGold)) { - console.info('Total value of grant less than CELO for beneficiary addreess') - return - } - - const adjustedAmountPerPeriod = totalValue.minus(startGold).div(config.numReleasePeriods).dp(0) - - // Reflect any rounding changes from the division above - totalValue = adjustedAmountPerPeriod.multipliedBy(config.numReleasePeriods) - - const contractInitializationArgs = [ - Math.round(releaseStartTime), - config.releaseCliffTime, - config.numReleasePeriods, - config.releasePeriod, - adjustedAmountPerPeriod.toFixed(), - config.revocable, - config.beneficiary, - config.releaseOwner, - config.refundAddress, - config.subjectToLiquidityProvision, - config.initialDistributionRatio, - config.canValidate, - config.canVote, - celoRegistryAddress, - ] - - const bytecode = await web3.eth.getCode(config.beneficiary) - if (bytecode !== '0x') { - const response = await prompts({ - type: 'confirm', - name: 'confirmation', - message: `Beneficiary ${config.beneficiary} is a smart contract which might cause loss of funds if not properly configured. Are you sure you want to continue? (y/n)`, - }) - - if (!response.confirmation) { - console.info(chalk.yellow('Skipping grant due to user response')) - return - } - } - - const message = - 'Please review this grant before you deploy:\n\tTotal Grant Value: ' + - Number(config.numReleasePeriods) * Number(config.amountReleasedPerPeriod) + - '\n\tGrant Recipient ID: ' + - config.identifier + - '\n\tGrant Beneficiary address: ' + - config.beneficiary + - '\n\tGrant Start Date (Unix timestamp): ' + - Math.floor(releaseStartTime) + - '\n\tGrant Cliff time (in seconds): ' + - config.releaseCliffTime + - '\n\tGrant num periods: ' + - config.numReleasePeriods + - '\n\tRelease Period length: ' + - config.releasePeriod + - (argv.debug - ? '\n\tDebug: Contract init args: ' + JSON.stringify(contractInitializationArgs) - : '') + - '\n\tDeploy this grant? (y/n)' - - if (!argv.yesreally) { - const response = await prompts({ - type: 'confirm', - name: 'confirmation', - message, - }) - - if (!response.confirmation) { - console.info(chalk.yellow('Skipping grant due to user response')) - return - } - } - console.info(' Deploying ReleaseGoldMultiSigProxy...') - const releaseGoldMultiSigProxy = await retryTx(ReleaseGoldMultiSigProxy.new, [ - { from: fromAddress }, - ]) - console.info(' Deploying ReleaseGoldMultiSig...') - const releaseGoldMultiSigInstance = await retryTx(ReleaseGoldMultiSig.new, [ - false, - { from: fromAddress }, - ]) - const multiSigTxHash = await _setInitialProxyImplementation( - web3, - releaseGoldMultiSigInstance, - releaseGoldMultiSigProxy, - 'ReleaseGoldMultiSig', - { - from: fromAddress, - value: null, - }, - [config.releaseOwner, config.beneficiary], - 2, - 2 - ) - await retryTx(releaseGoldMultiSigProxy._transferOwnership, [ - releaseGoldMultiSigProxy.address, - { - from: fromAddress, - }, - ]) - console.info(' Deploying ReleaseGoldProxy...') - const releaseGoldProxy = await retryTx(ReleaseGoldProxy.new, [{ from: fromAddress }]) - console.info(' Deploying ReleaseGold...') - const releaseGoldInstance = await retryTx(ReleaseGold.new, [false, { from: fromAddress }]) - - console.info('Initializing ReleaseGoldProxy...') - let releaseGoldTxHash - try { - releaseGoldTxHash = await _setInitialProxyImplementation( - web3, - releaseGoldInstance, - releaseGoldProxy, - 'ReleaseGold', - { - from: fromAddress, - value: totalValue.toFixed(), - }, - ...contractInitializationArgs - ) - } catch (e) { - console.info( - 'Something went wrong! Consider using the recover-funds.ts script with the below address' - ) - console.info('ReleaseGoldProxy', releaseGoldProxy.address) - throw e - } - const proxiedReleaseGold = await ReleaseGold.at(releaseGoldProxy.address) - await retryTx(proxiedReleaseGold.transferOwnership, [ - releaseGoldMultiSigProxy.address, - { - from: fromAddress, - }, - ]) - await retryTx(releaseGoldProxy._transferOwnership, [ - releaseGoldMultiSigProxy.address, - { from: fromAddress }, - ]) - - // Send starting gold amount to the beneficiary so they can perform transactions. - console.info(' Sending beneficiary starting gold...') - await retryTx(web3.eth.sendTransaction, [ - { - from: fromAddress, - to: config.beneficiary, - value: startGold, - }, - ]) - - const record = { - GrantNumber: currGrant, - Identifier: config.identifier, - Beneficiary: config.beneficiary, - ContractAddress: releaseGoldProxy.address, - MultiSigProxyAddress: releaseGoldMultiSigProxy.address, - MultiSigTxHash: multiSigTxHash, - ReleaseGoldTxHash: releaseGoldTxHash, - } - - deployedGrants.push(config.identifier) - releases.push(record) - console.info('Deployed grant', record) - // Must write to file after every grant to avoid losing info on crash. - fs.writeFileSync(deployedGrantsFile, JSON.stringify(deployedGrants, null, 1)) - fs.writeFileSync(argv.output_file, JSON.stringify(releases, null, 2)) -} - -async function checkBalance(config: ReleaseGoldConfig) { - const weiAmountReleasedPerPeriod = new BigNumber( - web3.utils.toWei(config.amountReleasedPerPeriod.toString()) - ) - const grantDeploymentCost = weiAmountReleasedPerPeriod - .multipliedBy(config.numReleasePeriods) - .plus(ONE_CELO) // Tx Fees - .toFixed() - while (true) { - const fromBalance = new BigNumber(await web3.eth.getBalance(fromAddress)) - if (fromBalance.gte(grantDeploymentCost)) { - break - } - console.info( - chalk.yellow( - fromAddress + - "'s balance will not cover the next grant with identifier " + - config.identifier + - '.' - ) - ) - const addressResponse = await prompts({ - type: 'text', - name: 'newFromAddress', - message: - "If you would like to continue deployment from a new address please provide it now. If you would like to cancel deployment please enter 'exit'. Grants already deployed will persist. \ - \nNote that the key for the current `from` address needs to remain accessible in order to roll funds over to the new `from` address.", - }) - - if (addressResponse.newFromAddress === 'exit') { - console.info('Exiting because of user input.') - process.exit(0) - } - - if (!web3.utils.isAddress(addressResponse.newFromAddress)) { - console.info( - chalk.red('Provided address is invalid, please insert a valid Celo Address.\nRetrying.') - ) - continue - } - // Must be enough to handle 1CELO test transfer and 1CELO for transaction fees - if (fromBalance.gt(TWO_CELO)) { - console.info( - '\nSending 1 CELO as a test from ' + - fromAddress + - ' to ' + - addressResponse.newFromAddress + - ' to verify ownership.\n' - ) - await retryTx(web3.eth.sendTransaction, [ - { - from: fromAddress, - to: addressResponse.newFromAddress, - value: ONE_CELO, - }, - ]) - const confirmResponse = await prompts({ - type: 'confirm', - name: 'confirmation', - message: - 'Please check the balance of your provided address. You should see the 1CELO transfer and an initial genesis balance if this is a shard from the genesis block.\nCan you confirm this (y/n)?', - }) - if (!confirmResponse.confirmation) { - console.info(chalk.red('Setting new address failed.\nRetrying.')) - continue - } - console.info(chalk.green('\nTransfer confirmed, sending the remaining balance.\n')) - const fromBalancePostTransfer = new BigNumber(await web3.eth.getBalance(fromAddress)) - await retryTx(web3.eth.sendTransaction, [ - { - from: fromAddress, - to: addressResponse.newFromAddress, - value: fromBalancePostTransfer.minus(ONE_CELO).toFixed(), // minus Tx Fees - }, - ]) - } - const switchResponse = await prompts({ - type: 'confirm', - name: 'confirmation', - message: - 'Please now switch your local wallet from ' + - fromAddress + - ' to ' + - addressResponse.newFromAddress + - '.\nIf you respond `n` here the script will exit because balance has already been sent.\nPlease confirm when you are able to switch (y/n)?', - }) - if (!switchResponse.confirmation) { - console.info(chalk.red('Switching wallets abandoned, exiting.')) - process.exit(0) - } - fromAddress = addressResponse.newFromAddress - } -} - -async function compile(template: ReleaseGoldTemplate): Promise { - const isUnspecified = (value: any): boolean => { - return value === undefined || value === null - } - - const questions = [] - if (isUnspecified(template.identifier)) { - questions.push({ - type: 'text', - name: 'identifier', - message: 'Identifier', - }) - } - if (isUnspecified(template.releaseStartTime)) { - questions.push({ - type: 'text', - name: 'releaseStartTime', - inital: 'MAINNET+0', - message: 'Release start time', - }) - } - if (isUnspecified(template.releaseCliffTime)) { - questions.push({ - type: 'number', - name: 'releaseCliffTime', - message: 'Release cliff time', - min: 0, - }) - } - if (isUnspecified(template.numReleasePeriods)) { - questions.push({ - type: 'number', - name: 'numReleasePeriods', - message: 'Number of release periods', - min: 1, - }) - } - if (isUnspecified(template.releasePeriod)) { - questions.push({ - type: 'number', - name: 'releasePeriod', - message: 'Release period time', - min: 1, - }) - } - if (isUnspecified(template.amountReleasedPerPeriod)) { - questions.push({ - type: 'number', - name: 'amountReleasedPerPeriod', - message: 'Amount released per period', - min: 0, - }) - } - if (isUnspecified(template.revocable)) { - questions.push({ - type: 'toggle', - name: 'revocable', - message: 'Revocable?', - }) - } - if (isUnspecified(template.beneficiary)) { - questions.push({ - type: 'text', - name: 'beneficiary', - message: 'Beneficiary', - initial: (_, { identifier }) => - isValidAddress(identifier ?? template.identifier) ? identifier : null, - validate: (value) => - isValidAddress(value) && value !== ZERO_ADDRESS - ? true - : 'Please enter a valid non-zero Celo address.', - }) - } - if (isUnspecified(template.releaseOwner)) { - questions.push({ - type: 'text', - name: 'releaseOwner', - message: 'Release owner', - validate: (value) => - isValidAddress(value) && value !== ZERO_ADDRESS - ? true - : 'Please enter a valid non-zero Celo address.', - }) - } - if (isUnspecified(template.refundAddress)) { - questions.push({ - type: 'text', - name: 'refundAddress', - message: 'Refund address', - initial: ZERO_ADDRESS, - validate: (value) => (isValidAddress(value) ? true : 'Please enter a valid Celo address.'), - }) - } - if (isUnspecified(template.subjectToLiquidityProvision)) { - questions.push({ - type: 'toggle', - name: 'subjectToLiquidityProvision', - message: 'Subject to liquidity provision?', - }) - } - if (isUnspecified(template.initialDistributionRatio)) { - questions.push({ - type: 'number', - name: 'initialDistributionRatio', - message: 'Initial distribution ratio', - initial: 1000, - min: 0, - max: 1000, - }) - } - if (isUnspecified(template.canValidate)) { - questions.push({ - type: 'toggle', - name: 'canValidate', - message: 'Can validate?', - }) - } - if (isUnspecified(template.canVote)) { - questions.push({ - type: 'toggle', - name: 'canVote', - message: 'Can vote?', - }) - } - - if (questions.length === 0) { - return template as ReleaseGoldConfig - } - - const onCancel = () => { - console.error('Exiting because input canceled.') - process.exit(0) - } - - console.info( - `\nGrant: ${JSON.stringify(template, undefined, 2)}\nUnspecified: ${questions - .map((q) => q.name) - .join(', ')}` - ) - const config: ReleaseGoldConfig = { - ...template, - // @ts-ignore: onSubmit is erroneously required in the type. - ...(await prompts(questions, { onCancel })), - } - return config -} - -async function handleJSONFile(data) { - const templates: ReleaseGoldTemplate[] = JSON.parse(data) - const grants: ReleaseGoldConfig[] = [] - for (const t of templates) { - grants.push(await compile(t)) - } - - if (grants.length === 0) { - console.error( - chalk.red('Provided grants file ' + argv.grants + ' does not contain any grants.\nExiting.') - ) - return - } - - console.info('Verifying grants have not already been deployed.') - for (const grant of grants) { - if (deployedGrants.includes(grant.identifier)) { - console.info( - chalk.red( - 'Grant with identifier ' + grant.identifier + ' has already been deployed.\nExiting.' - ) - ) - process.exit(0) - } - // Sum occurences of each identifier in the grant file, if more than 1 then there is a duplicate. - const identifierCounts = grants.map((x) => (x.identifier === grant.identifier ? 1 : 0)) - if (identifierCounts.reduce((a, b) => a + b, 0) > 1) { - console.info( - chalk.red( - 'Provided grant file ' + - argv.grants + - ' contains a duplicate identifier: ' + - grant.identifier + - '.\nExiting.' - ) - ) - process.exit(0) - } - } - - // Each grant type has a defined template - either they can validate and can't be revoked, - // or vice versa. Their distribution ratios and liquidity provisions should be the same. - // We check the first grant here and use that as a template for all grants - // to verify the grant file is uniformly typed to hopefully avoid user errors. - const template = { - revocable: grants[0].revocable, - canVote: grants[0].canVote, - canValidate: grants[0].canValidate, - subjectToLiquidityProvision: grants[0].subjectToLiquidityProvision, - initialDistributionRatio: grants[0].initialDistributionRatio, - } - if (!argv.yesreally) { - grants.map((grant) => { - if ( - grant.revocable !== template.revocable || - grant.canVote !== template.canVote || - grant.canValidate !== template.canValidate || - grant.subjectToLiquidityProvision !== template.subjectToLiquidityProvision || - grant.initialDistributionRatio !== template.initialDistributionRatio - ) { - console.error( - chalk.red( - 'Grants are not uniformly typed.\nWe expect all grants of a given JSON to have the same boolean values for `revocable`, `canVote`, `canValidate`, and `subjectToLiquidityProvision`, as well as having the same value for `initialDistributionRatio`.\nExiting' - ) - ) - process.exit(0) - } - }) - } - - const totalValue = grants.reduce((sum: number, curr: any) => { - return sum + Number(curr.amountReleasedPerPeriod) * Number(curr.numReleasePeriods) - }, 0) - const fromBalance = new BigNumber(await web3.eth.getBalance(fromAddress)) - if (!argv.yesreally) { - const response = await prompts({ - type: 'confirm', - name: 'confirmation', - message: - 'Grants in provided json would send ' + totalValue.toString() + 'CELO.\nIs this OK (y/n)?', - }) - - if (!response.confirmation) { - console.info(chalk.red('Abandoning grant deployment due to user response.')) - process.exit(0) - } - } - - // Check first provided address' balance - if (fromBalance.lt(await web3.utils.toWei(totalValue.toFixed()))) { - console.info( - chalk.yellow( - '\nError: The provided `from` address ' + - fromAddress + - "'s balance of " + - fromBalance + - ' is not sufficient to cover all of the grants specified in ' + - argv.grants + - '.\nYou will need to provide supplementary addresses (additional shards) to fund these grants.' - ) - ) - const response = await prompts({ - type: 'confirm', - name: 'confirmation', - message: 'If you know what you are doing, continue: (y/n)', - }) - - if (!response.confirmation) { - console.info(chalk.red('Abandoning grant deployment due to user response.')) - process.exit(0) - } - } - let currGrant = 1 - for (const config of grants) { - // Trim whitespace in case of bad copy/paste in provided json. - config.beneficiary = config.beneficiary.trim() - config.identifier = config.identifier.trim() - await checkBalance(config) - await handleGrant(config, currGrant) - currGrant++ - } - console.info(chalk.green('Grants deployed successfully.')) -} - -module.exports = async (callback: (error?: any) => number) => { - try { - argv = require('minimist')(process.argv.slice(5), { - string: [ - 'network', - 'from', - 'grants', - 'start_gold', - 'deployed_grants', - 'output_file', - 'really', - 'debug', - ], - }) - ReleaseGoldMultiSig = artifacts.require('ReleaseGoldMultiSig') - ReleaseGoldMultiSigProxy = artifacts.require('ReleaseGoldMultiSigProxy') - ReleaseGold = artifacts.require('ReleaseGold') - ReleaseGoldProxy = artifacts.require('ReleaseGoldProxy') - releases = [] - fromAddress = argv.from - startGold = web3.utils.toWei(argv.start_gold) - deployedGrantsFile = argv.deployed_grants - try { - deployedGrants = JSON.parse(fs.readFileSync(deployedGrantsFile, 'utf-8')) - } catch (e) { - // If this fails, file must be created - fs.writeFile(deployedGrantsFile, '', (err) => { - if (err) { - throw err - } - }) - deployedGrants = [] - } - - if (!argv.yesreally) { - const response = await prompts({ - type: 'confirm', - name: 'confirmation', - message: - 'Provided `deployedGrants` file includes ' + - deployedGrants.length + - ' deployed grant identifiers.\nPlease verify this matches your expectations. (y/n)', - }) - - if (!response.confirmation) { - console.info(chalk.red('Abandoning grant deployment due to user response.')) - process.exit(0) - } - } - try { - releases = JSON.parse(fs.readFileSync(argv.output_file, 'utf-8')) - } catch (e) { - // If this fails, file must be created - fs.writeFile(argv.output_file, '', (err) => { - if (err) { - throw err - } - }) - releases = [] - } - fs.readFile(argv.grants, async (err, data) => { - if (err) { - throw err - } - await handleJSONFile(data) - // Indicate success and exit. - callback() - }) - } catch (error) { - callback(error) - } -} diff --git a/packages/protocol/scripts/truffle/deployedGrants.json b/packages/protocol/scripts/truffle/deployedGrants.json deleted file mode 100644 index 0d4f101c7..000000000 --- a/packages/protocol/scripts/truffle/deployedGrants.json +++ /dev/null @@ -1,2 +0,0 @@ -[ -] diff --git a/packages/protocol/scripts/truffle/govern.ts b/packages/protocol/scripts/truffle/govern.ts deleted file mode 100644 index 91e3eee73..000000000 --- a/packages/protocol/scripts/truffle/govern.ts +++ /dev/null @@ -1,55 +0,0 @@ -/* tslint:disable:no-console */ -import assert = require('assert') - -import { - getDeployedProxiedContract, - submitMultiSigTransaction, -} from '@celo/protocol/lib/web3-utils' -import { MultiSigInstance } from 'types' - -/* - * A simple script to process transactions via a MultiSig - * - * Expects the following flags: - * command: the command to run - * - * Run using truffle exec, e.g.: - * truffle exec scripts/truffle/govern.js --command 'stableToken.setMinter(0xdeadbeef)' - * - */ -module.exports = async (callback: (error?: any) => number) => { - try { - const argv = require('minimist')(process.argv.slice(2), { - string: ['command'], - }) - - const multiSig = await getDeployedProxiedContract('MultiSig', artifacts) - - // TODO(asa): Validate function arguments - assert(RegExp('^[A-z]+.[A-z]+(.*)$').test(argv.command)) - - let contract - const [contractName, functionCall] = argv.command.split('.') - if (contractName.includes('Proxy')) { - const Proxy: Truffle.Contract = artifacts.require(contractName) - contract = await Proxy.deployed() - } else { - contract = await getDeployedProxiedContract(contractName, artifacts) - } - - const functionName = functionCall.split('(')[0] - const functionArgs = functionCall.split('(')[1].split(')')[0].split(', ') - - console.log(contractName, contract.address, functionName, functionArgs) - console.log('Calling', '"' + argv.command + '"', 'via MultiSig') - await submitMultiSigTransaction( - multiSig, - contract.address, - // @ts-ignore There is a property 'contract' on the variable contract - contract.contract[functionName].getData(...functionArgs) - ) - callback() - } catch (error) { - callback(error) - } -} diff --git a/packages/protocol/scripts/truffle/make-release.ts b/packages/protocol/scripts/truffle/make-release.ts deleted file mode 100644 index 60e2b557b..000000000 --- a/packages/protocol/scripts/truffle/make-release.ts +++ /dev/null @@ -1,375 +0,0 @@ -// tslint:disable: max-classes-per-file -// tslint:disable: no-console -// tslint:disable: ordered-imports -import { LibraryAddresses } from '@celo/protocol/lib/bytecode' -import { ASTDetailedVersionedReport } from '@celo/protocol/lib/compatibility/report' -import { getCeloContractDependencies } from '@celo/protocol/lib/contract-dependencies' -import { CeloContractName, celoRegistryAddress } from '@celo/protocol/lib/registry-utils' - -import { SOLIDITY_08_PACKAGE } from '@celo/protocol/contractPackages' -import { makeTruffleContractForMigrationWithoutSingleton } from '@celo/protocol/lib/web3-utils' -import { Address, NULL_ADDRESS, eqAddress } from '@celo/utils/lib/address' -import { TruffleContract } from '@truffle/contract' - -import { readJsonSync, readdirSync, writeJsonSync } from 'fs-extra' -import { basename, join } from 'path' -import { RegistryInstance } from 'types' -import { getReleaseVersion, ignoredContractsV9 } from '../../lib/compatibility/ignored-contracts-v9' -import { networks } from '../../truffle-config.js' - -/* - * A script that reads a backwards compatibility report, deploys changed contracts, and creates - * a corresponding JSON file to be proposed with `celocli governance:propose` - * - * Expects the following flags: - * report: The filepath of the backwards compatibility report - * network: The network for which artifacts should be - * - * Run using truffle exec, e.g.: - * truffle exec scripts/truffle/make-release \ - * --network alfajores --build_directory build/alfajores/ --report report.json \ - * --initialize_data initialize_data.json --proposal proposal.json - */ - -let ignoredContractsSet = new Set() - -function delay(time) { - return new Promise((resolve) => setTimeout(resolve, time)) -} - -function getRandomNumber(min: number, max: number): number { - return Math.floor(Math.random() * (max - min + 1) + min) -} - -class ContractAddresses { - static async create( - contracts: string[], - registry: RegistryInstance, - libraryAddresses: LibraryAddresses['addresses'] - ) { - const addresses = new Map() - await Promise.all( - contracts.map(async (contract: string) => { - // without this delay it sometimes fails with ProviderError - await delay(getRandomNumber(1, 1000)) - try { - const registeredAddress = await registry.getAddressForString(contract) - - if (!eqAddress(registeredAddress, NULL_ADDRESS)) { - addresses.set(contract, registeredAddress) - } - } catch (error) { - console.log('contract', contract, error) - throw error - } - }) - ) - Object.entries(libraryAddresses).forEach(([library, address]) => - addresses.set(library, address) - ) - return new ContractAddresses(addresses) - } - - constructor(public addresses: Map) {} - - public get = (contract: string): Address => { - if (this.addresses.has(contract)) { - return this.addresses.get(contract) - } else { - throw new Error(`Unable to find address for ${contract}`) - } - } - - public set = (contract: string, address: Address) => { - this.addresses.set(contract, address) - } -} - -const isProxiedContract = (contractName: string) => { - if (contractName.endsWith('Proxy')) { - return false - } - - try { - artifacts.require(`${contractName}Proxy`) - return true - } catch (error) { - return false - } -} - -const isCoreContract = (contractName: string) => - Object.keys(CeloContractName).includes(contractName) - -const deployImplementation = async ( - contractName: string, - Contract: TruffleContract, - dryRun: boolean, - from: string, - requireVersion = true -) => { - const testingDeployment = false - if (from) { - Contract.defaults({ from }) // override truffle with provided from address - } - console.log(`Deploying ${contractName}`) - // Hack to trick truffle, which checks that the provided address has code - - // without this delay it sometimes fails with ProviderError - await delay(getRandomNumber(1, 1000)) - - const contract = await (dryRun - ? Contract.at(celoRegistryAddress) - : Contract.new(testingDeployment)) - - // Sanity check that any contracts that are being changed set a version number. - const getVersionNumberAbi = contract.abi.find( - (abi: any) => abi.type === 'function' && abi.name === 'getVersionNumber' - ) - if (requireVersion && !getVersionNumberAbi) { - throw new Error(`Contract ${contractName} has changes but does not specify a version number`) - } - return contract -} - -const deployProxy = async ( - contractName: string, - addresses: ContractAddresses, - dryRun: boolean, - from: string -) => { - // Explicitly forbid upgrading to a new Governance proxy contract. - // Upgrading to a new Governance proxy contract would require ownership of all - // contracts to be moved to the new governance contract, possibly including contracts - // deployed in this script. - // Because this depends on ordering (i.e. was the new GovernanceProxy deployed - // before or after other contracts in this script?), and that ordering is not being - // checked, fail if there are storage incompatible changes to Governance. - if (contractName === 'Governance') { - throw new Error(`Storage incompatible changes to Governance are not yet supported`) - } - console.log(`Deploying ${contractName}Proxy`) - const Proxy = await artifacts.require(`${contractName}Proxy`) - if (from) { - Proxy.defaults({ from }) // override truffle with provided from address - } - // Hack to trick truffle, which checks that the provided address has code - const proxy = await (dryRun ? Proxy.at(celoRegistryAddress) : Proxy.new()) - - // This makes essentially every contract dependent on Governance. - console.log(`Transferring ownership of ${contractName}Proxy to Governance`) - if (!dryRun) { - await proxy._transferOwnership(addresses.get('Governance')) - } - - return proxy -} - -const shouldDeployProxy = (report: ASTDetailedVersionedReport, contractName: string) => { - const hasStorageChanges = report.contracts[contractName].changes.storage.length > 0 - const isNewContract = report.contracts[contractName].changes.major.find( - (change: any) => change.type === 'NewContract' - ) - return hasStorageChanges || isNewContract -} - -const deployCoreContract = async ( - contractName: string, - instance: Truffle.Contract, - proposal: ProposalTx[], - addresses: ContractAddresses, - report: ASTDetailedVersionedReport, - initializationData: any, - isDryRun: boolean, - from: string -) => { - const contract = await deployImplementation(contractName, instance, isDryRun, from) - const setImplementationTx: ProposalTx = { - contract: `${contractName}Proxy`, - function: '_setImplementation', - args: [contract.address], - value: '0', - } - - if (!shouldDeployProxy(report, contractName)) { - proposal.push(setImplementationTx) - } else { - const proxy = await deployProxy(contractName, addresses, isDryRun, from) - - // Update the contract's address to the new proxy in the proposal - addresses.set(contractName, proxy.address) - proposal.push({ - contract: 'Registry', - function: 'setAddressFor', - args: [contractName, proxy.address], - value: '0', - description: `Registry: ${contractName} -> ${proxy.address}`, - }) - - // If the implementation has an initialize function, add it to the proposal - const initializeAbi = (contract as any).abi.find( - (abi: any) => abi.type === 'function' && abi.name === 'initialize' - ) - if (initializeAbi) { - const args = initializationData[contractName] - let callData - try { - callData = web3.eth.abi.encodeFunctionCall(initializeAbi, args) - } catch (error) { - throw new Error( - `Tried to initialize new implementation of ${contractName} with args: ${JSON.stringify( - args - )}. Initialization ABI spec is: ${JSON.stringify(initializeAbi.inputs)}.` - ) - } - setImplementationTx.function = '_setAndInitializeImplementation' - setImplementationTx.args.push(callData) - } - console.log( - `Add '${contractName}.${setImplementationTx.function} with ${setImplementationTx.args}' to proposal` - ) - proposal.push(setImplementationTx) - } -} - -const deployLibrary = async ( - contractName: string, - contractArtifact: Truffle.Contract, - addresses: ContractAddresses, - isDryRun: boolean, - from: string -) => { - const contract = await deployImplementation(contractName, contractArtifact, isDryRun, from, false) - addresses.set(contractName, contract.address) - return -} - -export interface ProposalTx { - contract: string - function: string - args: string[] - value: string - description?: string -} - -module.exports = async (callback: (error?: any) => number) => { - try { - const argv = require('minimist')(process.argv.slice(2), { - string: [ - 'report', - 'from', - 'proposal', - 'librariesFile', - 'initialize_data', - 'build_directory', - 'branch', - ], - boolean: ['dry_run'], - }) - const fullReport = readJsonSync(argv.report) - const libraryMapping: LibraryAddresses['addresses'] = readJsonSync( - argv.librariesFile ?? 'libraries.json' - ) - const report: ASTDetailedVersionedReport = fullReport.report - const branch = (argv.branch ? argv.branch : '') as string - const initializationData = readJsonSync(argv.initialize_data) - const dependencies = getCeloContractDependencies() - - const version = getReleaseVersion(branch) - - if (version >= 9) { - ignoredContractsSet = new Set(ignoredContractsV9) - } - - const contracts08 = readdirSync(join(argv.build_directory, 'contracts-0.8')) - - const contracts = readdirSync(join(argv.build_directory, 'contracts')) - .concat(contracts08) // adding at the end so libraries that are already deployed don't get redeployed - .map((x) => basename(x, '.json')) - .filter( - (contract) => - !ignoredContractsSet.has(contract) && - !ignoredContractsSet.has(contract.replace('Proxy', '')) - ) - - const registry = await artifacts.require('Registry').at(celoRegistryAddress) - const addresses = await ContractAddresses.create(contracts, registry, libraryMapping) - const released: Set = new Set([]) - const proposal: ProposalTx[] = [] - - const release = async (contractNameIn: string) => { - const contractName = contractNameIn // not sure this will be needed - - // 0. Skip already released dependencies - if (released.has(contractName)) { - return - } - - console.log('Dependencies for contract', contractName) - - let contractArtifact - - try { - contractArtifact = await artifacts.require(contractName) - } catch { - // it wasn't found in the standard artifacts folder, check if it's 0.8 contract - // TODO this needs generalization to support more packages - // https://github.com/celo-org/celo-monorepo/issues/10563 - contractArtifact = makeTruffleContractForMigrationWithoutSingleton( - contractName, - { ...networks[argv.network], name: argv.network }, - SOLIDITY_08_PACKAGE.name, - web3 - ) - // TODO WARNING: make sure there are no libraries with the same name that don't get deployed - } - const shouldDeployContract = Object.keys(report.contracts).includes(contractName) - const shouldDeployLibrary = Object.keys(report.libraries).includes(contractName) - - if (shouldDeployContract) { - // Don't try to deploy and link libraries of contracts it doesn't have to deploy - // 1. Release all dependencies. Guarantees library addresses are canonical for linking. - const contractDependencies = dependencies.get(contractName) - for (const dependency of contractDependencies) { - console.log('Releasing dependency', dependency) - await release(dependency) - } - // 2. Link dependencies. - await Promise.all( - contractDependencies.map((d) => contractArtifact.link(d, addresses.get(d))) - ) - // 3. Deploy new versions of the contract or library, if indicated by the report. - console.log('Deploying Contract:', contractName) - await deployCoreContract( - contractName, - contractArtifact, - proposal, - addresses, - report, - initializationData, - argv.dry_run, - argv.from - ) - } else if (shouldDeployLibrary) { - console.log('Deploying library:', contractName) - await deployLibrary(contractName, contractArtifact, addresses, argv.dry_run, argv.from) - } else { - console.log('Not deployed:', contractName, "(it's not included in the report)") - } - - // 4. Mark the contract as released - released.add(contractName) - } - - for (const contractName of contracts) { - if (isCoreContract(contractName) && isProxiedContract(contractName)) { - await release(contractName) - } - } - - writeJsonSync(argv.proposal, proposal, { spaces: 2 }) - callback() - } catch (error) { - callback(error) - } -} diff --git a/packages/protocol/scripts/truffle/recover-funds.ts b/packages/protocol/scripts/truffle/recover-funds.ts deleted file mode 100644 index 65e057c5e..000000000 --- a/packages/protocol/scripts/truffle/recover-funds.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { recoverFunds } from '../../lib/recover-funds' - -module.exports = async (callback: (error?: any) => number) => { - const argv = require('minimist')(process.argv.slice(5), { - string: ['release_gold', 'from'], - }) - - await recoverFunds(argv.release_gold, argv.from) - console.info(' Funds recovered successfully!') - callback() -} diff --git a/packages/protocol/scripts/truffle/releaseGoldExampleConfigs.json b/packages/protocol/scripts/truffle/releaseGoldExampleConfigs.json deleted file mode 100644 index bd8b934e5..000000000 --- a/packages/protocol/scripts/truffle/releaseGoldExampleConfigs.json +++ /dev/null @@ -1,34 +0,0 @@ -[ - { - "identifier": "0x111111111", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 0, - "numReleasePeriods": 1, - "releasePeriod": 300000000, - "amountReleasedPerPeriod": 10002, - "revocable": false, - "beneficiary": "0x5409ED021D9299bf6814279A6A1411A7e866A631", - "releaseOwner": "0x6Ecbe1DB9EF729CBe972C83Fb886247691Fb6beb", - "refundAddress": "0x0000000000000000000000000000000000000000", - "subjectToLiquidityProvision": true, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": true - }, - { - "identifier": "0x222222222", - "releaseStartTime": "MAINNET", - "releaseCliffTime": 0, - "numReleasePeriods": 1, - "releasePeriod": 300000000, - "amountReleasedPerPeriod": 12, - "revocable": true, - "beneficiary": "0x6Ecbe1DB9EF729CBe972C83Fb886247691Fb6beb", - "releaseOwner": "0x5409ED021D9299bf6814279A6A1411A7e866A631", - "refundAddress": "0x5409ED021D9299bf6814279A6A1411A7e866A631", - "subjectToLiquidityProvision": false, - "initialDistributionRatio": 1000, - "canVote": true, - "canValidate": false - } -] diff --git a/packages/protocol/scripts/truffle/set_block_gas_limit.ts b/packages/protocol/scripts/truffle/set_block_gas_limit.ts deleted file mode 100644 index 44d2b95f7..000000000 --- a/packages/protocol/scripts/truffle/set_block_gas_limit.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* tslint:disable:no-console */ -import { - getDeployedProxiedContract, - transferOwnershipOfProxyAndImplementation, -} from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { BlockchainParametersInstance, GovernanceInstance } from 'types' - -/* - * A simple script to set the block gas limit after migrations - */ -module.exports = async (callback: (error?: any) => number) => { - try { - const bcp = await getDeployedProxiedContract( - 'BlockchainParameters', - artifacts - ) - console.log('Setting block gas limit to', config.blockchainParameters.blockGasLimit) - await bcp.setBlockGasLimit(config.blockchainParameters.blockGasLimit) - if (!config.governance.skipTransferOwnership) { - const governance = await getDeployedProxiedContract( - 'Governance', - artifacts - ) - await transferOwnershipOfProxyAndImplementation( - 'BlockchainParameters', - governance.address, - artifacts - ) - } - callback() - } catch (error) { - callback(error) - } -} diff --git a/packages/protocol/scripts/truffle/verify-bytecode.ts b/packages/protocol/scripts/truffle/verify-bytecode.ts deleted file mode 100644 index f1fcf28ab..000000000 --- a/packages/protocol/scripts/truffle/verify-bytecode.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { verifyBytecodes } from '@celo/protocol/lib/compatibility/verify-bytecode' -import { CeloContractName, celoRegistryAddress } from '@celo/protocol/lib/registry-utils' -import { getBuildArtifacts } from '@openzeppelin/upgrades' -import { readJsonSync, writeJsonSync } from 'fs-extra' -import { ProxyInstance, RegistryInstance } from 'types' -import { getReleaseVersion } from '../../lib/compatibility/ignored-contracts-v9' - -/* - * This script verifies that a given set of smart contract bytecodes corresponds - * to a Celo system deployed to a given network. It uses the Registry contract - * as its source of truth, potentially modified by an optional contract upgrade - * proposal description. - * - * Expects the following flags: - * --build_artifacts: The directory in which smart contract build artifacts - * can be found (default: "./build/contracts/") - * --proposal: The JSON file containing a Governance proposal that - * repoints the Registry to newly deployed Proxies and/or repoints existing - * Proxies to new implementation addresses. - * --initialize_data: The JSON file containing, for each newly deployed Proxy, - * the calldata to its logic contract's `initialize` function. - * --network: The name of the network to verify (default: "development"). - * --librariesFile: The file to which linked library addresses will be - * written (default: "libraries.json"). - * - * Run using truffle exec, e.g.: - * truffle exec scripts/truffle/verify-bytecode \ - * --network alfajores --build_artifacts build/alfajores/contracts --proposal proposal.json - */ - -const Registry: Truffle.Contract = artifacts.require('Registry') -const Proxy: Truffle.Contract = artifacts.require('Proxy') - -const argv = require('minimist')(process.argv.slice(2), { - string: ['build_artifacts', 'proposal', 'initialize_data', 'network', 'librariesFile', 'branch'], -}) - -const artifactsDirectory = argv.build_artifacts ? argv.build_artifacts : './build/contracts' -const branch = (argv.branch ? argv.branch : '') as string -const network = argv.network ?? 'development' -const proposal = argv.proposal ? readJsonSync(argv.proposal) : [] -const initializationData = argv.initialize_data ? readJsonSync(argv.initialize_data) : {} -const librariesFile = argv.librariesFile ?? 'libraries.json' - -module.exports = async (callback: (error?: any) => number) => { - try { - const version = getReleaseVersion(branch) - - const registry = await Registry.at(celoRegistryAddress) - const buildArtifacts = getBuildArtifacts(artifactsDirectory) - const libraryAddresses = await verifyBytecodes( - Object.keys(CeloContractName), - buildArtifacts, - registry, - proposal, - Proxy, - web3, - initializationData, - version, - network - ) - - // tslint:disable-next-line: no-console - console.log('Success, no bytecode mismatches found!') - - // tslint:disable-next-line: no-console - console.log(`Writing linked library addresses to ${librariesFile}`) - writeJsonSync(librariesFile, libraryAddresses.addresses, { spaces: 2 }) - } catch (error) { - callback(error) - } -} diff --git a/packages/protocol/scripts/truffle/verify_release_gold_contracts.ts b/packages/protocol/scripts/truffle/verify_release_gold_contracts.ts deleted file mode 100644 index af0390cea..000000000 --- a/packages/protocol/scripts/truffle/verify_release_gold_contracts.ts +++ /dev/null @@ -1,153 +0,0 @@ -import chalk from 'chalk' -import fs = require('fs') -import { - ReleaseGoldContract, - ReleaseGoldMultiSigContract, - ReleaseGoldMultiSigProxyContract, - ReleaseGoldProxyContract, -} from 'types' - -let argv: any -let contracts: any -let configs: any -let ReleaseGold: ReleaseGoldContract -let ReleaseGoldProxy: ReleaseGoldProxyContract -let ReleaseGoldMultiSig: ReleaseGoldMultiSigContract -let ReleaseGoldMultiSigProxy: ReleaseGoldMultiSigProxyContract -// const ONE_CGLD = web3.utils.toWei('1', 'ether') - -async function verifyContract(contract: any, config: any) { - let verified = true - // Balance check should only be used immediately after contract deployments. - // Otherwise, balances may increase via rewards, or decrease via withdrawals, leading to false negatives. - // verified = verified && (await verifyBalance(contract.ContractAddress, config)) - verified = verified && (await verifyMultisig(contract.MultiSigProxyAddress, config)) - verified = - verified && - (await verifyReleaseGold(contract.ContractAddress, contract.MultiSigProxyAddress, config)) - return verified -} - -async function verifyMultisig(multiSigAddress: any, config: any) { - const releaseGoldMultiSig = await ReleaseGoldMultiSig.at(multiSigAddress) - let contractOwners = await releaseGoldMultiSig.getOwners() - let configOwners = [config.beneficiary, config.releaseOwner] - contractOwners = contractOwners.map((x) => x.toLowerCase()) - configOwners = configOwners.map((x) => x.toLowerCase()) - for (let i = 0; i < contractOwners.length; i++) { - if (contractOwners.indexOf(configOwners[i]) === -1) { - console.info( - chalk.red( - "Multisig contracts' owners are not properly set to `beneficiary` and `releaseOwner`. This is possible (if the user elected to change their beneficiary) but uncommon." - ) - ) - return false - } - } - const releaseGoldMultiSigProxy = await ReleaseGoldMultiSigProxy.at(multiSigAddress) - if ( - (await releaseGoldMultiSigProxy._getOwner()).toLowerCase() !== multiSigAddress.toLowerCase() - ) { - console.info(chalk.red('ReleaseGoldMultiSigProxy is not properly set.')) - return false - } - return true -} - -async function verifyReleaseGold(releaseGoldAddress: any, multiSigAddress: any, config: any) { - const releaseGold = await ReleaseGold.at(releaseGoldAddress) - const releaseGoldProxy = await ReleaseGoldProxy.at(releaseGoldAddress) - if ((await releaseGold.owner()).toLowerCase() !== multiSigAddress.toLowerCase()) { - console.info(chalk.red('ReleaseGold owner not properly set.')) - return false - } - if ((await releaseGoldProxy._getOwner()).toLowerCase() !== multiSigAddress.toLowerCase()) { - console.info(chalk.red('ReleaseGoldProxy owner not properly set')) - return false - } - if ((await releaseGold.beneficiary()).toLowerCase() !== config.beneficiary.toLowerCase()) { - console.info(chalk.red('Beneficiary from config does not match contract')) - return false - } - return true -} - -// Uncomment if using `verifyBalance` just after contract deployment. -// async function verifyBalance(contractAddress: any, releaseGoldConfig: any) { -// const contractBalance = new BigNumber(await web3.eth.getBalance(contractAddress)) -// const weiAmountReleasedPerPeriod = new BigNumber( -// web3.utils.toWei(releaseGoldConfig.amountReleasedPerPeriod.toString()) -// ) -// let configValue = weiAmountReleasedPerPeriod.multipliedBy(releaseGoldConfig.numReleasePeriods) -// const adjustedAmountPerPeriod = configValue -// .minus(ONE_CGLD) -// .div(releaseGoldConfig.numReleasePeriods) -// .dp(0) - -// // Reflect any rounding changes from the division above -// configValue = adjustedAmountPerPeriod.multipliedBy(releaseGoldConfig.numReleasePeriods) -// if (!contractBalance.eq(configValue)) { -// console.info(chalk.yellow("Contract balance does not match configured amount. This is likely because of the balance increasing from rewards or users sending more CELO, please verify:\nConfigured amount:" + configValue.toFixed() + ", Contract Balance:" + contractBalance.toFixed())) -// return false -// } -// return true -// } - -function findConfigByID(identifier) { - for (const config of configs) { - if (config.identifier === identifier) { - return config - } - } - return null -} - -module.exports = async (callback: (error?: any) => number) => { - try { - argv = require('minimist')(process.argv.slice(3), { - string: ['network', 'contracts_file', 'config_file'], - }) - try { - contracts = JSON.parse(fs.readFileSync(argv.contract_json, 'utf-8')) - configs = JSON.parse(fs.readFileSync(argv.config_json, 'utf-8')) - } catch (e) { - console.info('Fail - bad file given, error: ' + e) - process.exit(0) - } - if (contracts.length !== configs.length) { - console.info('Lengths do not match, exiting') - process.exit(0) - } - const failures = [] - ReleaseGold = artifacts.require('ReleaseGold') - ReleaseGoldProxy = artifacts.require('ReleaseGoldProxy') - ReleaseGoldMultiSig = artifacts.require('ReleaseGoldMultiSig') - ReleaseGoldMultiSigProxy = artifacts.require('ReleaseGoldMultiSigProxy') - for (const contract of contracts) { - const config = findConfigByID(contract.Identifier) - if (config === null) { - console.info( - 'Identifier: ' + contract.Identifier + ' from contracts file not found in configs file.' - ) - process.exit(0) - } - if (!(await verifyContract(contract, config))) { - console.info( - chalk.red( - 'MISMATCH: Contract with identifier ' + contract.Identifier + ' is not verified.' - ) - ) - failures.push(contract.Identifier) - } - } - if (failures.length > 0) { - console.info( - failures.length + - ' mismatches were identified, please review the output identifiers above.\nOutputting failures to `failureOutput.json`.' - ) - fs.writeFileSync('failureOutput.json', JSON.stringify(failures, null, 2)) - } - } catch (error) { - callback(error) - } -} diff --git a/packages/protocol/specs/README.md b/packages/protocol/specs/README.md deleted file mode 100644 index ea37bb6b2..000000000 --- a/packages/protocol/specs/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# Certora Specs - -This directory contains all necessary material in order to execute the Certora Prover: spec files, run scripts, and harnesses. - -## Spec files - -### Accounts -- `accounts.spec` - general rules for the Accounts contract. -- `accountsPrivileged.spec` - rule for identifying the privileged subset of functions, that is, functions that can only be executed by a single party. - -### LockedGold -- `lockedGold.spec` - general rules for the LockedGold contract. -- `locked_gold_linked.spec` - rules for LockedGold that are coupled with Accounts. - -### Governance -- `governance.spec` - general rules for the Governance contract. (Not exhaustive.) -- `governancePrivileged.spec` - rule for identifying the privileged subset of functions, that is, functions that can only be executed by a single party. -- `governance_with_dequeue.spec` - rules for Governance that require reasoning about the dequeue mechanism -- `governance_old_rules.spec` - rules used in the 2019 formal verification project, and require some re-formulation. -- `governance-referendumVotes.spec` - a rule checking the consistency of referendum votes. diff --git a/packages/protocol/specs/accounts.spec b/packages/protocol/specs/accounts.spec deleted file mode 100644 index 9572c29f6..000000000 --- a/packages/protocol/specs/accounts.spec +++ /dev/null @@ -1,476 +0,0 @@ -pragma specify 0.1 - -methods { - isAccount(address) returns bool envfree - isSigner(address,address,bytes32) returns bool envfree // account, signer, role - _getAuthorizedBy(address) returns address envfree - _getDataEncryptionKeyLen(address) returns uint256 - _getNameLen(address) returns uint256 - getWalletAddress(address) returns address envfree - getAttestationSigner(address) returns address envfree - _getAttestationSigner(address) returns address envfree - getVoteSigner(address) returns address envfree - _getVoteSigner(address) returns address envfree - getValidatorSigner(address) returns address envfree - _getValidatorSigner(address) returns address envfree - getDefaultSigner(address,bytes32) returns address envfree - _getDefaultSigner(address,bytes32) returns address envfree - getLegacySigner(address,bytes32) returns address envfree - isLegacyRole(bytes32) returns bool envfree - isCompletedSignerAuthorization(address,bytes32,address) returns bool envfree - isStartedSignerAuthorization(address,bytes32,address) returns bool envfree - voteSignerToAccount(address) returns address envfree - validatorSignerToAccount(address) returns address envfree - attestationSignerToAccount(address) returns address envfree - signerToAccount(address) returns address envfree - _getValidatorRole() returns bytes32 envfree - _getAttestationRole() returns bytes32 envfree - _getVoteRole() returns bytes32 envfree - getIndexedSigner(address,bytes32) returns address envfree -} - -/** - * If an address x is not an account then all mapping from x should be empty - */ -invariant account_empty_if_not_exist(env e, address x) - !isAccount(x) => - getWalletAddress(x) == 0 && - _getAttestationSigner(x) == 0 && - _getVoteSigner(x) == 0 && - _getValidatorSigner(x) == 0 - - -/** - * An address d that is authorized by some account x can not become an account - */ -invariant address_cant_be_both_account_and_signer(address x, address d) - (x != 0 && d != 0 && x != d && _getAuthorizedBy(d) == x) => - (isAccount(x) && !isAccount(d)) - - -/** - * A current signer d or account x should be authorizedby for legacy roles - */ -invariant address_signer_if_authorizedby_legacy(address x, address d) - (x != d && x != 0 && d != 0 && - (_getAttestationSigner(x) == d || _getVoteSigner(x) == d || _getValidatorSigner(x) == d)) - => (isAccount(x) && _getAuthorizedBy(d) == x) - -/** - * A current signer d or account x should be authorizedby for new roles - */ -invariant address_signer_if_authroizedby_new(address x, address d, bytes32 role) - (x != d && x != 0 && d != 0 && - _getDefaultSigner(x,role) == d) - => (isAccount(x) && _getAuthorizedBy(d) == x) - -/** - * Given account x, address d a current signer, then d can not be a current signer of account y - * (Expensive rule) - */ - /* -rule address_cant_be_both_authorizedby_of_two_address(address x, address y, address d, bytes32 r1, bytes32 r2, method f) filtered { f -> !f.isView } { - // x and y are accounts d is authorizedby - require x != 0 && y != 0 && d != 0 && x != d && y != x && y != d; - // x is not registered or authorized - require isAccount(x) && _getAuthorizedBy(d) == x; - // y is not a registered account - require isAccount(y); - // d must be a signer of some capacity for x - require getIndexedSigner(x, r1) == d; - // d must not be a signer of any capacity for y - require getIndexedSigner(y, r2) != d; - - // Simulate all possible execution of all methods - callArbitrary(f); - - // Check that d is still not a current signer of y of any type - assert getIndexedSigner(y, r2) != d, - "d must still not be a signer of any capacity for y"; -} -*/ - -/** - * Account x can have two authorized addresses - legacy - */ -rule address_can_authorize_two_addresses_legacy(address x, address d1, address d2) -{ - require x != 0 && d1 != 0 && d2 != 0 && x != d1 && x != d2 && d1 != d2 && isAccount(x); - env e; - require e.msg.sender == x; - - storage init = lastStorage; - // first, authorizing d2 as a validation signer should succeed - uint8 v2; - bytes32 r2; - bytes32 s2; - authorizeValidatorSigner(e, d2, v2, r2, s2); - - // Authorize d1 as a Vote signer (alternative execution path - start from the state where validator authorization started) - uint8 v1; - bytes32 r1; - bytes32 s1; - authorizeVoteSigner(e, d1, v1, r1, s1) at init; - - // Even after authorizing d1, the authorization of d2 as a Validation signer should succeed - authorizeValidatorSigner(e, d2, v2, r2, s2); - - // AuthorizedBy(d1) and AuthorizedBy(d2) should still be x - assert _getAuthorizedBy(d1) == x && _getAuthorizedBy(d2) == x, "Authorizedby should both be x"; -} - -/** - * Account x can have two authorized addresses - new - */ -rule address_can_authorize_two_addresses(address x, address d1, address d2, bytes32 role1, bytes32 role2) -{ - require x != 0 && d1 != 0 && d2 != 0 && x != d1 && x != d2 && d1 != d2 && isAccount(x); - env e; - require e.msg.sender == x; - - storage init = lastStorage; - // first, authorizing d2 as a validation signer should succeed - uint8 v2; - bytes32 r2; - bytes32 s2; - authorizeSignerWithSignature(e, d2, role2, v2, r2, s2); - - // Authorize d1 as a Vote signer (alternative execution path - start from the state where validator authorization started) - uint8 v1; - bytes32 r1; - bytes32 s1; - authorizeSignerWithSignature(e, d1, role1, v1, r1, s1) at init; - - // Even after authorizing d1, the authorization of d2 as a Validation signer should succeed - authorizeSignerWithSignature(e, d2, role2, v2, r2, s2); - - // AuthorizedBy(d1) and AuthorizedBy(d2) should still be x - assert _getAuthorizedBy(d1) == x && _getAuthorizedBy(d2) == x, "Authorizedby should both be x"; -} - -/** - * Either the account's authorized signer doesn't change, or it gets set from when it's 0. - */ -rule authorizedBy_can_not_be_removed(method f, address signer) filtered { f -> !f.isView } { - address _account = _getAuthorizedBy(signer); - callArbitrary(f); - address account_ = _getAuthorizedBy(signer); - // Whatever transacation occurs, if `_account` was authorized before, it remains authorized. - // If `_account` was null, then we could authorize a new account `account_`. - assert _account == account_ || _account == 0, - "Account delegating to $signer cannot change from one non-zero value to another non-zero value"; -} - -/** - * A second call to initialize must fail - */ -rule initializableOnlyOnce { - env e; - calldataarg arg; - initialize(e, arg); - - env e2; - calldataarg arg2; - initialize@withrevert(e2, arg2); - assert lastReverted; -} - -/** - * Only `createAccount` should be creating an account - */ -rule createsAccount(method f, address a) filtered { f -> - !f.isView - && f.selector != createAccount().selector - && f.selector != setAccount(string,bytes,address,uint8,bytes32,bytes32).selector -} { - bool _isAccount = isAccount(a); - callArbitrary(f); - bool isAccount_ = isAccount(a); - - assert _isAccount == isAccount_, "checked function creates an account"; -} - -/** - * A legacy role should never be set in default signers indexing map (because we have direct struct access in storage) - */ -invariant legacyRolesAreNotUsedInNewRoles(address account, bytes32 role) - isLegacyRole(role) => _getDefaultSigner(account, role) == 0 - -/** - * view functions in general should not revert. - * Some exceptions and more refined revert-characteristics are provided. - */ -rule viewFunctionsDoNotRevert(method f) filtered { f -> - f.isView - // some functions we ignore, and the reasons: - && f.selector != hasAuthorizedSigner(address,string).selector // Calldatasize may not match - && f.selector != batchGetMetadataURL(address[]).selector // Calldatasize may not match - - // These require an account to exist - && f.selector != getOffchainStorageRoots(address).selector - && f.selector != offchainStorageRoots(address,uint256).selector -} { - env e; - require e.msg.value == 0; // view functions are not payable - - // functions that require special handling: - if (f.selector == getLegacySigner(address,bytes32).selector) { - // getLegacySigner requires getting a legacy role - address a; - bytes32 r; - require isLegacyRole(r); - getLegacySigner@withrevert(a, r); - } else if (f.selector == hasLegacySigner(address,bytes32).selector) { - // hasLegacySigner requires getting a legacy role - address a; - bytes32 r; - require isLegacyRole(r); - hasLegacySigner@withrevert(e, a, r); - } else if (f.selector == signerToAccount(address).selector) { - // will fail if address is not authorized by anyone, and is not an account. - address a; - require _getAuthorizedBy(a) != 0 || isAccount(a); - signerToAccount@withrevert(a); - } else if (f.selector == voteSignerToAccount(address).selector) { - address a; - address authBy = _getAuthorizedBy(a); - requireInvariant authorizedByIsNeverReflexive(a); - require (authBy != 0 && isSigner(authBy, a, _getVoteRole())) || (authBy == 0 && isAccount(a)); - voteSignerToAccount@withrevert(a); - } else if (f.selector == validatorSignerToAccount(address).selector) { - address a; - address authBy = _getAuthorizedBy(a); - requireInvariant authorizedByIsNeverReflexive(a); - require (authBy != 0 && isSigner(authBy, a, _getValidatorRole())) || (authBy == 0 && isAccount(a)); - validatorSignerToAccount@withrevert(a); - } else if (f.selector == attestationSignerToAccount(address).selector) { - address a; - address authBy = _getAuthorizedBy(a); - requireInvariant authorizedByIsNeverReflexive(a); - require (authBy != 0 && isSigner(authBy, a, _getAttestationRole())) || (authBy == 0 && isAccount(a)); - attestationSignerToAccount@withrevert(a); - } else { - calldataarg arg; - f@withrevert(e, arg); - } - - assert !lastReverted, "View functions should not revert"; -} - -/** - * the authorizedBy should never be reflexive, i.e. an account cannot be its own signer, or a signer cannot be authroize itself. - */ -invariant authorizedByIsNeverReflexive(address a) - a != 0 => _getAuthorizedBy(a) != a - -/** - * If we set signerAuthroization to be completed, it means the signer is marked as authorizedBy the account. - * The other direction may not be correct because authorizedBy is persistent while signer authorizations can be removed. - */ -invariant mustHaveAuthorizedByIfCompletedSignerAuthorization(address account, bytes32 role, address signer) - account != 0 => (isCompletedSignerAuthorization(account, role, signer) => _getAuthorizedBy(signer) == account) - -/** - * For signerAuthorization, a signer can only appear as a signer of a single account. - */ -invariant noMultipleAccountsPerSignerInARole(address account, address account2, bytes32 role, bytes32 role2, address signer) - account != 0 && account2 != 0 - => (isCompletedSignerAuthorization(account, role, signer) && isCompletedSignerAuthorization(account2, role2, signer) - => account == account2) { - - preserved { - requireInvariant mustHaveAuthorizedByIfCompletedSignerAuthorization(account, role, signer); - requireInvariant mustHaveAuthorizedByIfCompletedSignerAuthorization(account2, role2, signer); - } -} - -/** - * Only legacy roles allow to jump from no signer authorization being started, to being completed, in one single invocation. - */ -rule cantGoFromNoAuthorizationToCompletedInOneStepUnlessRoleIsLegacy(method f) filtered { f -> - !f.isView - // the authorizeSignerWithSignature allows the signer to provide a signature to the account, so we exclude this option - && f.selector != authorizeSignerWithSignature(address,bytes32,uint8,bytes32,bytes32).selector -} { - address account; - bytes32 role; - address signer; - require !isStartedSignerAuthorization(account, role, signer) && !isCompletedSignerAuthorization(account, role, signer); - - callArbitrary(f); - - assert isCompletedSignerAuthorization(account, role, signer) => isLegacyRole(role); -} - -/** - * One cannot complete the signer authorization process unless the signer itself signs on the transaction, - * or the signer provided a signature. - */ -rule cantMakeASignerForNonLegacyRoleWithoutApprovalOfSigner(method f) filtered { f -> - !f.isView - // the authorizeSignerWithSignature allows the signer to provide a signature to the account, so we exclude this option - && f.selector != authorizeSignerWithSignature(address,bytes32,uint8,bytes32,bytes32).selector -} { - address account; - bytes32 role; - - // Leagcy roles can be updated using a signature - require !isLegacyRole(role); - - address signer; - - // not completed signer auth yet (but may have started) - require !isCompletedSignerAuthorization(account, role, signer); - - env e; - calldataarg arg; - f(e, arg); - - assert isCompletedSignerAuthorization(account, role, signer) => e.msg.sender == signer; -} - -/** - * One cannot start a signer authorization on behalf of another account. - */ -rule cannotStartSignerAuthorizationsForOtherAccounts(method f) filtered { f -> !f.isView } { - address account; - bytes32 role; - address signer; - require !isStartedSignerAuthorization(account, role, signer); - - env e; - calldataarg arg; - f(e,arg); - - assert isStartedSignerAuthorization(account, role, signer) => e.msg.sender == account; -} - -/** - * The only way authorizedBy should be set is using a signature, or by the signer being the caller - */ -rule cannotSetAuthorizedByWithoutSignatures(method f) filtered { f -> - !f.isView - && f.selector != authorizeSignerWithSignature(address,bytes32,uint8,bytes32,bytes32).selector - && f.selector != authorizeAttestationSigner(address,uint8,bytes32,bytes32).selector - && f.selector != authorizeValidatorSigner(address,uint8,bytes32,bytes32).selector - && f.selector != authorizeValidatorSignerWithKeys(address,uint8,bytes32,bytes32,bytes,bytes,bytes).selector - && f.selector != authorizeValidatorSignerWithPublicKey(address,uint8,bytes32,bytes32,bytes).selector - && f.selector != authorizeVoteSigner(address,uint8,bytes32,bytes32).selector -} { - address d; - require _getAuthorizedBy(d) == 0; - - env e; - calldataarg arg; - f(e, arg); - - assert _getAuthorizedBy(d) == 0 || e.msg.sender == d; -} - -/** - * Conditions for being able to change signerAuthorization - */ -rule signerAuthorizationChangePrivileges(address a, bytes32 r, address s, method f) filtered { f -> - !f.isView -} { - bool _started = isStartedSignerAuthorization(a, r, s); - bool _completed = isCompletedSignerAuthorization(a, r, s); - - env e; - calldataarg arg; - f(e, arg); - - bool started_ = isStartedSignerAuthorization(a, r, s); - bool completed_ = isCompletedSignerAuthorization(a, r, s); - assert _started != started_ => e.msg.sender == a, "Only account can start a signer authorization"; - assert _completed && !completed_ => e.msg.sender == a, "Only account can remove a signer authorization"; - assert !_completed && completed_ => e.msg.sender == a || e.msg.sender == s, "Only signer or account can complete a signer authorization"; -} - -/** - * There's no contents to the fallback function - */ -rule check_no_fallback { - env e; - calldataarg arg; - invoke_fallback(e, arg); - - assert lastReverted; -} - -/** - * The values of get*Signer getters should be consistent for all roles. - */ -rule gettersInAgreement() { - address account; - require account != 0; - bytes32 role; - address indexedSigner = getIndexedSigner(account, role); - address defaultSigner = getDefaultSigner(account, role); - address legacySigner = getLegacySigner(account, role); - address voteSigner = getVoteSigner(account); - address validatorSigner = getValidatorSigner(account); - address attestationSigner = getAttestationSigner(account); - - if (role == _getVoteRole()) { - assert indexedSigner == legacySigner && indexedSigner == voteSigner, "indexed signer agrees with legacy signer for vote role"; - } else if (role == _getValidatorRole()) { - assert indexedSigner == legacySigner && indexedSigner == validatorSigner, "indexed signer agrees with legacy signer for validator role"; - } else if (role == _getAttestationRole()) { - assert indexedSigner == legacySigner && indexedSigner == attestationSigner, "indexed signer agrees with legacy signer for attestation role"; - } else { - assert indexedSigner == defaultSigner, "for any non legacy role indexed signer is default signer"; - } - - assert indexedSigner != 0 && defaultSigner != 0 && legacySigner != 0 - && voteSigner != 0 && validatorSigner != 0 && attestationSigner != 0, "signer is never address 0"; - - // original assertion is wrong - //assert indexedSigner != account => defaultSigner != account, "If indexed signer is a distinct address then default signer for this role is also a distinct address"; - assert !isLegacyRole(role) && indexedSigner != account => defaultSigner != account, "If indexed signer is a distinct address then default signer for this role is also a distinct address"; -} - -/** - * account to signer and signer to account getters should agree - */ -invariant accountToSignerAndInverseVote(address a, address s, bytes32 r) - r == _getVoteRole() => (s == getVoteSigner(a) => voteSignerToAccount(s) == a) -{ - preserved { - require a != s; - } -} - -invariant accountToSignerAndInverseValidator(address a, address s, bytes32 r) - r == _getValidatorRole() => (s == getValidatorSigner(a) => validatorSignerToAccount(s) == a) -{ - preserved { - require a != s; - } -} - -invariant accountToSignerAndInverseAttestation(address a, address s, bytes32 r) - r == _getAttestationRole() => (s == getAttestationSigner(a) => attestationSignerToAccount(s) == a) -{ - preserved { - require a != s; - } -} - -invariant accountToSignerAndInverseNewRoles(address a, address s, bytes32 r) - getIndexedSigner(a, r) == s => signerToAccount(s) == a -{ - preserved { - require a != s; - } -} - - -/** - * A utility for shortening calls to arbitrary functions in which we do not care about the environment. - */ -function callArbitrary(method f) { - env e; - calldataarg arg; - f(e, arg); -} diff --git a/packages/protocol/specs/accountsPrivileged.spec b/packages/protocol/specs/accountsPrivileged.spec deleted file mode 100644 index 19e293a6e..000000000 --- a/packages/protocol/specs/accountsPrivileged.spec +++ /dev/null @@ -1,50 +0,0 @@ -definition knownAsNonPrivileged(method f) returns bool = false - || f.selector == removeIndexedSigner(bytes32).selector - || f.selector == authorizeValidatorSignerWithPublicKey(address,uint8,bytes32,bytes32,bytes).selector - || f.selector == setAccountDataEncryptionKey(bytes).selector - || f.selector == removeVoteSigner().selector - || f.selector == authorizeValidatorSignerWithKeys(address,uint8,bytes32,bytes32,bytes,bytes,bytes).selector - || f.selector == authorizeVoteSigner(address,uint8,bytes32,bytes32).selector - || f.selector == authorizeSigner(address,bytes32).selector - || f.selector == setIndexedSigner(address,bytes32).selector - || f.selector == setMetadataURL(string).selector - || f.selector == addStorageRoot(bytes).selector - || f.selector == removeStorageRoot(uint256).selector - || f.selector == removeAttestationSigner().selector - || f.selector == authorizeAttestationSigner(address,uint8,bytes32,bytes32).selector - || f.selector == setAccount(string,bytes,address,uint8,bytes32,bytes32).selector - || f.selector == authorizeSignerWithSignature(address,bytes32,uint8,bytes32,bytes32).selector - || f.selector == setWalletAddress(address,uint8,bytes32,bytes32).selector - || f.selector == createAccount().selector - || f.selector == completeSignerAuthorization(address,bytes32).selector - || f.selector == removeValidatorSigner().selector - || f.selector == authorizeValidatorSigner(address,uint8,bytes32,bytes32).selector - || f.selector == setName(string).selector - || f.selector == initialize(address).selector - || f.selector == removeDefaultSigner(bytes32).selector - || f.selector == removeSigner(address,bytes32).selector - || f.selector == setEip712DomainSeparator().selector - || f.selector == setPaymentDelegation(address,uint256).selector - || f.selector == deletePaymentDelegation().selector - ; - -rule privilegedOperation(method f, address privileged) -description "$f can be called by more than one user without reverting" -{ - env e1; - calldataarg arg; - require !knownAsNonPrivileged(f); - require e1.msg.sender == privileged; - - storage initialStorage = lastStorage; - invoke f(e1, arg); // privileged succeeds executing candidate privileged operation. - bool firstSucceeded = !lastReverted; - - env e2; - calldataarg arg2; - require e2.msg.sender != privileged; - invoke f(e2, arg2) at initialStorage; // unprivileged - bool secondSucceeded = !lastReverted; - - assert !(firstSucceeded && secondSucceeded), "${f.selector} can be called by both ${e1.msg.sender} and ${e2.msg.sender}, so it is not privileged"; -} diff --git a/packages/protocol/specs/goverance_with_dequeue.spec b/packages/protocol/specs/goverance_with_dequeue.spec deleted file mode 100644 index ec0b54f2b..000000000 --- a/packages/protocol/specs/goverance_with_dequeue.spec +++ /dev/null @@ -1,74 +0,0 @@ -// these rules should be run on the original governance, without disabling dequeueing -rule may_dequeue(method f, uint256 index) filtered { f -> !f.isView } { - // a utility rule for figuring out which methods could dequeue and whether it's all due to dequeueProposalsIfReady calls. - - // require index to be valid and to be empty - require index >= 0; - uint256 queueLength = getDequeuedLength(); - require index <= queueLength || index == queueLength+1; // either an empty index or the next one we push - // if it's an empty index in the range, then it's empty - require index <= queueLength => getFromDequeued(index) == 0; - - callArbitrary(f); - - uint256 newValueInDequeued = getFromDequeued(index); - - assert newValueInDequeued == 0, "Method caused a dequeue of proposal $newValueInDequeued to index $index"; -} - -rule promote_proposal(method f, uint256 p, uint256 index) filtered { f -> !f.isView } { - /* A proposal should never be able to be promoted from the queue if it was proposed more than queueExpiry seconds ago */ - // Let's say we have an empty index. Then it cannot be filled with a new proposal p if its submit time is more than queueExpiry seconds ago - env eF; - - // p must be non zero - require p != 0; - - // get queue expiry - uint256 _queueExpiry = queueExpiry(); - - // require index to be valid and to be empty - require index >= 0; - uint256 queueLength = getDequeuedLength(); - require index <= queueLength || index == queueLength+1; // either an empty index or the next one we push - // if it's an empty index in the range, then it's empty - require index <= queueLength => getFromDequeued(index) == 0; - - // fetch proposal p timestamp - uint256 _proposalTimestamp; - _,_, _proposalTimestamp, _ = getProposalSlim(p); - - // invoke f - calldataarg arg; - require !f.isView; - sinvoke f(eF,arg); - - // deqeued index should contain p now only if eF.block.timestamp is not past p's timestamp+queueExpiry - assert getFromDequeued(index) == p => eF.block.timestamp <= _proposalTimestamp + _queueExpiry, - "Managed to promote $p in ${eF.block.timestamp} after proposal timestamp ${_proposalTimestamp} + ${_queueExpiry}"; -} - -/* -TODO: -A proposal should never be able to be promoted from the queue if it was not in the top concurrentProposals of upvote received -*/ -rule no_promoting_without_upvotes(uint256 p, uint256 index) { - // Can a proposal be promoted with 0 votes? - env _e; - env eF; - env e_; - - /* would actually want forall index. inrange(index) => dequeued[index] != p but here its suffice to 'pre-guess' the index of the proposal we dequeue */ - // require index to be valid and to be empty - require index >= 0; - require p > 0; // proposal 0 is not legal, and cannot happen (we check it) - uint256 queueLength = getDequeuedLength(); - require index <= queueLength || index == queueLength+1; // either an empty index or the next one we push - // if it's an empty index in the range, then it's empty - require index <= queueLength => getFromDequeued(index) == 0; - - uint256 _upvotes = getUpvotes(p); - - dequeueProposalsIfReady(eF); - assert getFromDequeued(index) == p => _upvotes > 0, "Cannot dequeue (promote) proposal $p to index $index unless had some upvotes"; -} \ No newline at end of file diff --git a/packages/protocol/specs/governance-referendumVotes.spec b/packages/protocol/specs/governance-referendumVotes.spec deleted file mode 100644 index 0a22430f3..000000000 --- a/packages/protocol/specs/governance-referendumVotes.spec +++ /dev/null @@ -1,29 +0,0 @@ - -// dequeue invariant -ghost votedFor(address,uint256) returns bool { // voter to proposal id voted for - init_state axiom forall address v. forall address p. !votedFor(v, p); -} - -ghost dequeuedArray(uint256) returns uint256; - -hook Sstore dequeued[INDEX uint256 i] uint256 id STORAGE { - havoc dequeuedArray assuming (forall uint256 j. j != i => dequeuedArray@new(j) == dequeuedArray@old(j) && dequeuedArray@new(i) == id); -} - -hook Sload uint256 id dequeued[INDEX uint256 i] STORAGE { - require dequeuedArray(i) == id; -} - -hook Sstore voters[KEY address x].(offset 96)/*referendumVotes*/[KEY uint256 indx].(offset 32)/*proposal ID */ uint256 id STORAGE { - require 0 <= x && x <= max_uint160; - havoc votedFor assuming votedFor@new(x,id) == true - && (forall address y. forall uint z. (y != x || z != id => votedFor@new(y,z) == votedFor@old(y,z))); -} - -invariant referendumVotesAreConsistent(address v, uint i, env e) - getVotedId(v,i) != 0 => (proposalExists(e, getVotedId(v,i)) => votedFor(v,getVotedId(v,i))) { - preserved { - requireInvariant referendumVoteIDIsLessThanOrEqCounter(v); - } -} - diff --git a/packages/protocol/specs/governance.spec b/packages/protocol/specs/governance.spec deleted file mode 100644 index 0023b0627..000000000 --- a/packages/protocol/specs/governance.spec +++ /dev/null @@ -1,390 +0,0 @@ -using Accounts as accounts - -methods { - vote(uint256,uint256,uint8) returns bool - - getProposalSlim(uint256) returns address, uint256, uint256, uint256 envfree - stageDurations() returns uint256,uint256,uint256 envfree - getUpvotes(uint256) returns uint256 envfree - getUpvotedProposal(address) returns uint256 envfree - getUpvoteRecord(address) returns uint256, uint256 envfree - getQueueLength() returns uint256 envfree - proposalCount() returns uint256 envfree - getDequeuedLength() returns uint256 envfree - getFromDequeued(uint256) returns uint256 envfree - queueExpiry() returns uint256 envfree - isApproved(uint256) returns bool envfree - isDequeuedProposalExpired(uint256) returns bool - getNoneVoteEnum() returns uint256 envfree - getAbstainVoteEnum() returns uint256 envfree - getYesVoteEnum() returns uint256 envfree - getNoVoteEnum() returns uint256 envfree - getTotalLockedGold() returns uint256 envfree - getVoteTotals(uint256) returns uint256,uint256,uint256 envfree - approver() returns address envfree - getVoteRecord(address,uint256) returns uint256, uint256, uint256 envfree - getMostRecentReferendumProposal(address) returns uint256 envfree - proposalExists(uint256) returns bool - getVotedId(address, uint256) returns uint256 envfree - - // dispatches to Accounts - voteSignerToAccount(address) => DISPATCHER(true) UNRESOLVED - getVoteSigner(address) returns address => DISPATCHER(true) UNRESOLVED - accounts.voteSignerToAccount(address) returns (address) envfree - accounts.getVoteSigner(address) returns (address) envfree -} - -ghost votedFor(address,uint256) returns bool { // voter to proposal id voted for - init_state axiom forall address v. forall address p. !votedFor(v, p); -} - -hook Sstore voters[KEY address x].(offset 96)/*referendumVotes*/[KEY uint256 indx].(offset 32)/*proposal ID */ uint256 id STORAGE { - require 0 <= x && x <= max_uint160; - havoc votedFor assuming votedFor@new(x,id) == true - && (forall address y. forall uint z. (y != x || z != id => votedFor@new(y,z) == votedFor@old(y,z))); -} - -ghost dequeuedArray(uint256) returns uint256; - -hook Sstore dequeued[INDEX uint256 i] uint256 id STORAGE { - havoc dequeuedArray assuming (forall uint256 j. j != i => dequeuedArray@new(j) == dequeuedArray@old(j) && dequeuedArray@new(i) == id); -} - -hook Sload uint256 id dequeued[INDEX uint256 i] STORAGE { - require dequeuedArray(i) == id; -} - -// consistency -invariant dequeuedIsWithinRange(uint i) getFromDequeued(i) <= proposalCount() - - -// upvoting -rule upvotesConsistency(address u, method f) filtered { f -> !f.isView } { - uint _p; - uint _w; - _p, _w = getUpvoteRecord(u); - - callArbitrary(f); - - uint p_; - uint w_; - p_, w_ = getUpvoteRecord(u); - assert (_p == p_ && _w == w_) || upvoteInv(p_, w_); - // the invariant is upvoteInv, defined here -} - -definition upvoteInv(uint p, uint w) returns bool - = (p != 0 && w > 0) || (p == 0 && w == 0) - ; - -rule no_double_upvote(uint256 p, address u) { - uint256 _upvotes = getUpvotes(p); - uint256 _usersUpvotedProposal = getUpvotedProposal(u); - env e; - require e.msg.sender == u && u != 0; // note that the sender is the signer here - require accounts.voteSignerToAccount(u) == u; - uint256 lesser; - uint256 greater; - upvote(e, p, lesser, greater); - uint256 upvotes_ = getUpvotes(p); - - uint voteRecordP; - uint voteRecordW; - voteRecordP, voteRecordW = getUpvoteRecord(u); - require upvoteInv(voteRecordP, voteRecordW); - assert _usersUpvotedProposal == p => upvotes_ <= _upvotes, - "Upvotes increased from ${_upvotes} to ${upvotes_} even though upvoted by user $u who already upvoted $p"; -} - -rule proposal_count_monotonic_increasing(method f) filtered { f -> !f.isView } { - // proposal count is monotonic increasing (strictly in propose) - - uint256 _count = proposalCount(); - - callArbitrary(f); - - uint256 count_ = proposalCount(); - - if (f.selector == propose(uint256[],address[],bytes,uint256[],string).selector && !f.isFallback) { - assert count_ > _count, "Successful propose must increase proposal count"; - assert count_ > 0, "Proposal cannot be 0"; // this is already obvious - even one proposal will increase count to 1 - } - - assert count_ >= _count, "Proposal count must not decrease"; -} - - -// referendum -rule no_referendum_votes_unless_approved(method f, uint256 p) filtered { f -> !f.isView } { - // A proposal should never be able to receive a vote unless it was approved - env eF; - - uint256 _yes; - uint256 _no; - uint256 _abstain; - _yes, _no, _abstain = getVoteTotals(p); - - // no votes currently - require _yes == 0 && _no == 0 && _abstain == 0; - - bool _isProposalApproved = isApproved(p); - - callArbitrary(f); - - uint256 yes_; - uint256 no_; - uint256 abstain_; - yes_, no_, abstain_ = getVoteTotals(p); - - assert (yes_ != 0 || no_ != 0 || abstain_ != 0) => _isProposalApproved, - "Cannot move from 0 votes to positive number of yes,no,abstain votes unless proposal $p is approved."; -} - -rule cant_unvote(uint256 deqIndex, uint8 voteValue) { - env eF; - uint256 NONE_ENUM = getNoneVoteEnum(); - // get the voting delegate - address voterDelegate = accounts.getVoteSigner(eF.msg.sender); - - // check if voted - uint256 p; - uint256 recordValue; - uint256 weight; - p, recordValue, weight = getVoteRecord(voterDelegate,deqIndex); - bool result = vote(eF,p,deqIndex,voteValue); - - uint256 recordValue_; - uint256 weight_; - _, recordValue_, weight_ = getVoteRecord(voterDelegate,deqIndex); - - assert voteValue == NONE_ENUM => (!result && recordValue_ == recordValue && weight_ == weight), "Cannot vote for none: function either returns false and did not update the vote, or it reverted"; // not voting none. reverting is fine and is encoded by the safe invoke -} - -/* A user that already has a vote record for a dequeued index, cannot make a transaction that will increase the weight of that choice */ -rule no_double_vote_referendum_all_but_vote(method f, address account, uint256 deqIndex) filtered { f -> !f.isView } { - env eF; - env eFTime; // same time as eF; - env e_; - - uint256 NONE_ENUM = getNoneVoteEnum(); - uint256 ABSTAIN = getAbstainVoteEnum(); - uint256 YES = getYesVoteEnum(); - uint256 NO = getNoVoteEnum(); - - uint256 p; // a proposal - let's assume it already exists (required for propose() verification) - uint256 recordValue; - p, recordValue, _ = getVoteRecord(account,deqIndex); - uint256 currentProposalCount = proposalCount(); - require currentProposalCount >= p; - - - uint256 _yes; uint256 _no; uint256 _abstain; - _yes,_no,_abstain = getVoteTotals(p); - - // if can't vote for NONE_ENUM, then necessarily if record vote is NONE_ENUM, all votes are zero currently - require recordValue == NONE_ENUM => (_yes == 0 && _no == 0 && _abstain == 0); - - - calldataarg arg; - require f.selector != vote(uint256,uint256,uint8).selector; - require f.selector != revokeVotes().selector; - require !f.isView; - require eF.msg.sender == account; - f(eF,arg); - - uint256 yes_; uint256 no_; uint256 abstain_; - yes_,no_,abstain_ = getVoteTotals(p); - - bool doesProposalExist_ = proposalExists(e_,p); - - // if p expires, then sum of votes is no longer relevant - happens in approve, vote, execute - assert (recordValue != NONE_ENUM && doesProposalExist_) => (yes_ + no_ + abstain_) == (_yes + _no + _abstain), "Total votes could not have changed if already voted"; - assert recordValue == YES => yes_ <= _yes, "Yes votes could not have increased if voted yes already"; - assert recordValue == NO => no_ <= _no, "No votes could not have increased if voted no already"; - assert recordValue == ABSTAIN => abstain_ <= _abstain, "Abstain votes could not have increased if voted abstain already"; - assert recordValue == NONE_ENUM => (!doesProposalExist_ && yes_ == 0 && no_ == 0 && abstain_ == 0) // proposal no longer exists so everything is 0 - // or no votes changed - || (yes_ == _yes && no_ == _no && abstain_ == _abstain), - "If previously did not vote, either this proposal was deleted, or no votes changed"; -} - -invariant referendumVoteIDIsLessThanOrEqCounter(address v, uint p) votedFor(v,p) => p <= proposalCount() { - preserved vote(uint256 _, uint256 indx, uint8 vr) with (env e) { - requireInvariant dequeuedIsWithinRange(indx); - } -} - -// approval -rule approval_only_if_promoted_and_allowed(uint256 p, uint256 index) { - // A proposal should never be able to be approved unless it was promoted from the queue - env eF; - env eGet; - require eF.block.timestamp == eGet.block.timestamp; - require eF.block.number == eGet.block.number; - - bool _isProposalApproved = isApproved(p); - bool _isDequeued = getFromDequeued(index) == p; - bool _isExpired = isDequeuedProposalExpired(eGet, p); - - address _approver = approver(); - require !_isProposalApproved; // we assume not approved yet - require !_isExpired; // we also assume it did not expire - - approve(eF,p,index); - // should check if dequeued right during approve - bool isDequeued_ = getFromDequeued(index) == p; - - bool isProposalApproved_ = isApproved(p); - - assert isProposalApproved_ => _isDequeued || (!_isDequeued && isDequeued_), "Cannot approve proposal $p unless $index points to it before approve or during it"; // index has p - assert isProposalApproved_ => eF.msg.sender == _approver, "Only approver ${_approver} can approve"; -} - -// proposalId is timestamp -rule approved_proposals_invariants(method f, uint256 p) filtered { f -> !f.isView } { - env _e; - env eF; - env e_; - - // Existence depends on timestamp, and we assume we are well past 0 - require e_.block.timestamp >= eF.block.timestamp - && eF.block.timestamp >= _e.block.timestamp - && _e.block.timestamp > 0; - - bool _doesProposalExist = proposalExists(_e,p); - bool _isApprovedProposal = isApproved(p); - - require _isApprovedProposal => _doesProposalExist; // if a proposal is approved, it must be existent - - calldataarg arg; - require !f.isView; - sinvoke f(eF,arg); - - bool doesProposalExist_ = proposalExists(e_,p); - bool isApprovedProposal_ = isApproved(p); - - assert isApprovedProposal_ => doesProposalExist_, "An approved proposal must exist"; - assert _isApprovedProposal => isApprovedProposal_ || !doesProposalExist_, "An approved proposal cannot be disapproved if it still exists"; -} - -// execute -rule execute_preconds(uint256 p, uint256 index) { - // A proposal should never be executable when there are at least as many no votes as yes votes - // TODO: A proposal should never be executable unless it received a yes:no vote ratio greater than that specified in the constitution - env _e; - env eF; - - uint256 _yes; - uint256 _no; - uint256 _abstain; - _yes, _no, _abstain = getVoteTotals(p); - - bool executeRetval = execute@withrevert(eF,p,index); - bool executeReverted = lastReverted; - - assert _no >= _yes => (!executeRetval || executeReverted), "If there are more no votes than yes votes, then we cannot succeed in executing"; - // TODO: may require to make sure that all constitutions demand at least majority -} - - -// exploring the state -rule modifying_stageDuration(method f) filtered { f -> - !f.isView - && f.selector != initialize(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256).selector - && f.selector != setApprovalStageDuration(uint256).selector - && f.selector != setExecutionStageDuration(uint256).selector - && f.selector != setReferendumStageDuration(uint256).selector -} { - uint256 old1; uint256 old2; uint256 old3; - old1, old2, old3 = stageDurations(); - - callArbitrary(f); - - uint256 new1; - uint256 new2; - uint256 new3; - new1, new2, new3 = stageDurations(); - - assert old1 == new1 && old2 == new2 && old3 == new3; -} - -rule can_add_to_queue(method f) filtered { f -> - !f.isView - && f.selector != propose(uint256[],address[],bytes,uint256[],string).selector -} { - uint256 _queueLength = getQueueLength(); - - callArbitrary(f); - - uint256 queueLength_ = getQueueLength(); - - assert queueLength_ <= _queueLength, - "Method can queue elements - should check separately that cannot queue proposal IDs equal 0 (proposal_count_monotonic_increasing)"; -} - -rule constitution_change(method f) filtered { f -> - !f.isView - && f.selector != setConstitution(address,bytes4,uint256).selector -} { - env _e; - env eF; - env e_; - - calldataarg arg_getConstitution; - - uint256 _res; - _res = getConstitution(_e,arg_getConstitution); - - callArbitrary(f); - - uint256 res_; - res_ = getConstitution(e_,arg_getConstitution); - - bool changed = !(_res == res_); - - // we're going to demand hard equality here - so 1/2 and 2/4 are INEQUAL - assert !changed, "changes constitution"; -} - -// initialization rules -rule only_initializer_changes_initialized_field(method f) filtered { f -> !f.isView } { - env _e; - env eF; - env e_; - - bool _isInitialized = initialized(_e); - - require f.selector != initialize(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256).selector; - - callArbitrary(f); - - bool isInitialized_ = sinvoke initialized(e_); - - assert _isInitialized == isInitialized_, "Method $f is not expected to change initialization field from ${_isInitialized} to ${isInitialized_}"; -} - -rule check_initializer { - env _e; - env eF; - env e_; - - bool _isInitialized = initialized(_e); - - calldataarg arg; - initialize@withrevert(eF,arg); - bool successInit = !lastReverted; - - bool isInitialized_ = initialized(e_); - - assert _isInitialized => !successInit, "initialize() must revert if already initialized"; - assert successInit => isInitialized_, "When initialize() succeeds, must set initialization field to true"; -} - -/** - * A utility for shortening calls to arbitrary functions in which we do not care about the environment. - */ -function callArbitrary(method f) { - env e; - calldataarg arg; - f(e, arg); -} diff --git a/packages/protocol/specs/governancePrivileged.spec b/packages/protocol/specs/governancePrivileged.spec deleted file mode 100644 index 2fa04357d..000000000 --- a/packages/protocol/specs/governancePrivileged.spec +++ /dev/null @@ -1,37 +0,0 @@ -definition knownAsNonPrivileged(method f) returns bool = false - || f.selector == dequeueProposalsIfReady().selector - || f.selector == withdraw().selector - || f.selector == execute(uint256,uint256).selector - || f.selector == upvote(uint256,uint256,uint256).selector - || f.selector == propose(uint256[],address[],bytes,uint256[],string).selector - || f.selector == revokeVotes().selector - || f.selector == revokeUpvote(uint256,uint256).selector - || f.selector == whitelistHotfix(bytes32).selector - || f.selector == vote(uint256,uint256,uint8).selector - || f.selector == initialize(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256).selector - || f.selector == prepareHotfix(bytes32).selector - || f.selector == executeHotfix(uint256[],address[],bytes,uint256[],bytes32).selector - || f.isFallback -; - - -rule privilegedOperation(method f, address privileged) -description "$f can be called by more than one user without reverting" -{ - env e1; - calldataarg arg; - require !knownAsNonPrivileged(f); - require e1.msg.sender == privileged; - - storage initialStorage = lastStorage; - invoke f(e1, arg); // privileged succeeds executing candidate privileged operation. - bool firstSucceeded = !lastReverted; - - env e2; - calldataarg arg2; - require e2.msg.sender != privileged; - invoke f(e2, arg2) at initialStorage; // unprivileged - bool secondSucceeded = !lastReverted; - - assert !(firstSucceeded && secondSucceeded), "${f.selector} can be called by both ${e1.msg.sender} and ${e2.msg.sender}, so it is not privileged"; -} diff --git a/packages/protocol/specs/governance_old_rules.spec b/packages/protocol/specs/governance_old_rules.spec deleted file mode 100644 index 3f761c3a5..000000000 --- a/packages/protocol/specs/governance_old_rules.spec +++ /dev/null @@ -1,111 +0,0 @@ - -/** Requires correction **/ - -rule no_double_vote_referendum_vote(address account, uint256 deqIndex) { - /* A user that already has a vote record for a dequeued index, cannot make a transaction that will increase the weight of that choice */ - env eF; - env eFTime; // same time as eF; - env e_; - - uint256 NONE_ENUM = getNoneVoteEnum(); - uint256 ABSTAIN = getAbstainVoteEnum(); - uint256 YES = getYesVoteEnum(); - uint256 NO = getNoVoteEnum(); - - uint256 p; // a proposal - let's assume it already exists (required for propose() verification) - uint256 recordValue; - p, recordValue, _ = getVoteRecord(account,deqIndex); - uint256 currentProposalCount = proposalCount(); - require currentProposalCount >= p; - - - uint256 _yes; uint256 _no; uint256 _abstain; - _yes,_no,_abstain = getVoteTotals(p); - - // if can't vote for NONE_ENUM, then necessarily if record vote is NONE_ENUM, all votes are zero currently - require recordValue == NONE_ENUM => (_yes == 0 && _no == 0 && _abstain == 0); - - require accounts.voteSignerToAccount(eF.msg.sender) == account; - uint256 someP; uint256 someIndex; uint8 someValue; - - uint256 pOfSomeIndex; - pOfSomeIndex, _, _ = getVoteRecord(account,someIndex); - require pOfSomeIndex == p => someIndex == deqIndex; // no duplicates in the dequeued array - require someP == p => someIndex == deqIndex; - - vote(eF,someP,someIndex,someValue); - - - uint256 yes_; uint256 no_; uint256 abstain_; - yes_,no_,abstain_ = getVoteTotals(p); - - bool doesProposalExist_ = proposalExists(e_,p); - - // if p expires, then sum of votes is no longer relevant - happens in approve, vote, execute - assert (recordValue != NONE_ENUM && doesProposalExist_) => (yes_ + no_ + abstain_) == (_yes + _no + _abstain), "Total votes could not have changed if already voted"; - assert recordValue == YES => yes_ <= _yes, "Yes votes could not have increased if voted yes already"; - assert recordValue == NO => no_ <= _no, "No votes could not have increased if voted no already"; - assert recordValue == ABSTAIN => abstain_ <= _abstain, "Abstain votes could not have increased if voted abstain already"; - assert recordValue == NONE_ENUM => (!doesProposalExist_ && yes_ == 0 && no_ == 0 && abstain_ == 0)// proposal no longer exists so everything is 0 - // or just one out of (yes,no,abstain) changed - || (yes_ == _yes && no_ == _no) - || (yes_ == _yes && abstain_ == _abstain) - || (no_ == _no && abstain_ == _abstain), - "If previously did not vote, either this proposal was deleted, or only one kind of vote may change, and the other two are the same"; -} - - -/* The sum of yes votes for a proposal cannot exceed total weight - requires linked LockedGold */ -// this rule requires linkage of LockedGold -rule sum_of_votes_cannot_exceed_total_weight(method f, uint256 p) filtered { f -> !f.isView } { - uint256 _totalWeight = getTotalLockedGold(); - // TODO: Must make sure that governance is not capable of invoking any function that changes the state of BondedDeposits and specifically totalWeight - - uint256 _yes; - uint256 _no; - uint256 _abstain; - _yes, _no, _abstain = getVoteTotals(p); - - require _yes+_no+_abstain <= _totalWeight; - - callArbitrary(f); - - uint256 totalWeight_ = getTotalLockedGold(); - - uint256 yes_; - uint256 no_; - uint256 abstain_; - yes_, no_, abstain_ = getVoteTotals(p); - - assert yes_+no_+abstain_ <= totalWeight_, "Sum of votes for a proposal cannot exceed total weight"; -} - - -rule constitution_change_legal(method f) filtered { f -> !f.isView } { - env _e; - env eF; - env e_; - - calldataarg arg_getConstitution; - - uint256 _res; - _res = getConstitution(_e,arg_getConstitution); - - callArbitrary(f); - - uint256 res_; - res_ = getConstitution(e_,arg_getConstitution); - - bool changed = !(_res == res_); - // TODO: This needs to be re-written based on new library for fractions - /* - bool b1 = num_*2 <= denom_; - bool b2 = num_ <= denom_; - - // if constitution is correct then we report that there was a change, but otherwise we report the incorrect change as well. - // if constitution updated, check if it is correct. - assert changed => b1, "Updated constitution: Constitution must be at least majority, but got less: ${num_} to ${denom_}"; - assert changed => b2, "Updated constitution: Constitution cannot demand more than unanimous, but got ${num_} to ${denom_}"; - */ - assert true; -} \ No newline at end of file diff --git a/packages/protocol/specs/harnesses/AccountsHarness.sol b/packages/protocol/specs/harnesses/AccountsHarness.sol deleted file mode 100644 index 7cff67cbc..000000000 --- a/packages/protocol/specs/harnesses/AccountsHarness.sol +++ /dev/null @@ -1,61 +0,0 @@ -pragma solidity ^0.5.13; - -import "contracts/common/Accounts.sol"; - -contract AccountsHarness is Accounts { - constructor(bool test) public Accounts(test) {} - - function _getAuthorizedBy(address signer) public view returns (address) { - return authorizedBy[signer]; - } - - function _getDataEncryptionKeyLen(address a) public view returns (uint256) { - return this.getDataEncryptionKey(a).length; - } - - function _getNameLen(address a) public view returns (uint256) { - return bytes(this.getName(a)).length; - } - - function _getVoteSigner(address account) public view returns (address) { - return accounts[account].signers.vote; - } - - function _getValidatorSigner(address account) public view returns (address) { - return accounts[account].signers.validator; - } - - function _getAttestationSigner(address account) public view returns (address) { - return accounts[account].signers.attestation; - } - - function _getDefaultSigner(address account, bytes32 role) public view returns (address) { - return defaultSigners[account][role]; - } - - function isCompletedSignerAuthorization(address account, bytes32 role, address signer) - public - view - returns (bool) - { - return signerAuthorizations[account][role][signer].completed; - } - - function isStartedSignerAuthorization(address account, bytes32 role, address signer) - public - view - returns (bool) - { - return signerAuthorizations[account][role][signer].started; - } - - function _getValidatorRole() public view returns (bytes32) { - return ValidatorSigner; - } - function _getVoteRole() public view returns (bytes32) { - return VoteSigner; - } - function _getAttestationRole() public view returns (bytes32) { - return AttestationSigner; - } -} diff --git a/packages/protocol/specs/harnesses/GoldTokenHarness.sol b/packages/protocol/specs/harnesses/GoldTokenHarness.sol deleted file mode 100644 index 756078d32..000000000 --- a/packages/protocol/specs/harnesses/GoldTokenHarness.sol +++ /dev/null @@ -1,22 +0,0 @@ -pragma solidity ^0.5.13; - -import "contracts/common/GoldToken.sol"; -import "openzeppelin-solidity/contracts/utils/Address.sol"; - -contract GoldTokenHarness is GoldToken { - using Address for address payable; // prettier-ignore - /* solhint-disable no-empty-blocks */ - function init_state() public {} - constructor(bool test) public GoldToken(test) {} - - function _transfer(address to, uint256 value) internal returns (bool) { - require(to != address(0), "Transfer attempted to reserved address 0x0"); - require(to != address(this), "GoldToken cannot transfer to itself"); - require(value <= balanceOf(msg.sender), "Transfer value exceeded balance of sender"); - - address(uint160(to)).sendValue(value); // TRANSFER.call.value(0).gas(gasleft())(abi.encode(msg.sender, to, value)); - emit Transfer(msg.sender, to, value); - return true; - } - -} diff --git a/packages/protocol/specs/harnesses/GovernanceHarness.sol b/packages/protocol/specs/harnesses/GovernanceHarness.sol deleted file mode 100644 index 00fac5e11..000000000 --- a/packages/protocol/specs/harnesses/GovernanceHarness.sol +++ /dev/null @@ -1,65 +0,0 @@ -pragma solidity ^0.5.13; - -import "contracts/governance/Governance.sol"; -import "contracts/governance/Proposals.sol"; -import "./LockedGoldHarness.sol"; - -contract GovernanceHarness is Governance { - using Proposals for Proposals.Proposal; - constructor(bool test) public Governance(test) {} - - function getDequeuedLength() public view returns (uint256) { - return dequeued.length; - } - - function getFromDequeued(uint256 index) public view returns (uint256) { - return dequeued[index]; // note that this can revert if index is unchecked - } - - // VoteValue - function getNoneVoteEnum() public pure returns (uint256) { - return uint256(VoteValue.None); - } - function getAbstainVoteEnum() public pure returns (uint256) { - return uint256(VoteValue.Abstain); - } - function getYesVoteEnum() public pure returns (uint256) { - return uint256(VoteValue.Yes); - } - function getNoVoteEnum() public pure returns (uint256) { - return uint256(VoteValue.No); - } - - /* Override */ - LockedGoldHarness lockedGold; - function getLockedGold() internal view returns (ILockedGold) { - return lockedGold; - } - - function getTotalLockedGold() public view returns (uint256) { - return lockedGold.getTotalLockedGold(); - } - - function getUpvotedProposal(address account) public view returns (uint256) { - uint256 proposalId; - uint256 weight; - (proposalId, weight) = this.getUpvoteRecord(account); - return proposalId; - } - - function getProposalSlim(uint256 proposalId) - external - view - returns (address, uint256, uint256, uint256) - { - Proposals.Proposal storage proposal = proposals[proposalId]; - return (proposal.proposer, proposal.deposit, proposal.timestamp, proposal.transactions.length); - } - - function getVotedId(address account, uint256 index) external view returns (uint256) { - return voters[account].referendumVotes[index].proposalId; - } - - // override for performance - do nothing - function dequeueProposalsIfReady() public {} -} diff --git a/packages/protocol/specs/harnesses/IRegistryExtended.sol b/packages/protocol/specs/harnesses/IRegistryExtended.sol deleted file mode 100644 index b9e70c840..000000000 --- a/packages/protocol/specs/harnesses/IRegistryExtended.sol +++ /dev/null @@ -1,12 +0,0 @@ -pragma solidity ^0.5.13; - -contract IRegistryExtended { - /* does not extend IRegistry to avoid overriding issues */ - // SG: Instrumentation - function isValidating(address) external returns (bool); - function getTotalWeight() external returns (uint256); - function getVoterFromAccount(address) external returns (address); - function getAccountWeight(address) external returns (uint256); - function getAccountFromVoter(address voter) external returns (address); - -} diff --git a/packages/protocol/specs/harnesses/LockedGoldHarness.sol b/packages/protocol/specs/harnesses/LockedGoldHarness.sol deleted file mode 100644 index 438a0dafb..000000000 --- a/packages/protocol/specs/harnesses/LockedGoldHarness.sol +++ /dev/null @@ -1,63 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "contracts/governance/LockedGold.sol"; -import "./GoldTokenHarness.sol"; - -contract LockedGoldHarness is LockedGold { - using SafeMath for uint256; - - GoldTokenHarness goldToken; - - constructor(bool test) public LockedGold(test) {} - - /* solhint-disable-next-line no-empty-blocks */ - function init_state() public {} - - function ercBalanceOf(address a) public returns (uint256) { - return a.balance; - } - - function getPendingWithdrawalsIndex(address account, uint256 index) public returns (uint256) { - require(getAccounts().isAccount(account), "Unknown account"); - require( - index < balances[account].pendingWithdrawals.length, - "Index cannot exceed pending withdrawals length" - ); - return balances[account].pendingWithdrawals[index].value; - } - - function getunlockingPeriod() public returns (uint256) { - return unlockingPeriod; - } - - function getTotalPendingWithdrawals(address account) public view returns (uint256) { - require(getAccounts().isAccount(account), "Unknown account"); - uint256 length = balances[account].pendingWithdrawals.length; - uint256 total = 0; - for (uint256 i = 0; i < length; i = i.add(1)) { - uint256 pendingValue = balances[account].pendingWithdrawals[i].value; - require(total.add(pendingValue) >= total, "Pending value must be greater than 0"); - total = total.add(pendingValue); - } - return total; - } - - function pendingWithdrawalsNotFull(address account) public view returns (bool) { - return balances[account].pendingWithdrawals.length.add(2) >= 2; // we can add 2 more additional elements - } - - function getPendingWithdrawalsLength(address account) external view returns (uint256) { - uint256 length = balances[account].pendingWithdrawals.length; - return length; - } - - function getGoldToken() internal view returns (IERC20) { - return IERC20(goldToken); - } - - function getGoldTokenExt() public view returns (address) { - return address(goldToken); - } -} diff --git a/packages/protocol/specs/harnesses/RegistryHarness.sol b/packages/protocol/specs/harnesses/RegistryHarness.sol deleted file mode 100644 index a27dddbeb..000000000 --- a/packages/protocol/specs/harnesses/RegistryHarness.sol +++ /dev/null @@ -1,151 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "./IRegistryExtended.sol"; - -contract RegistryHarness is IRegistryExtended { - using SafeMath for uint256; - - bytes32 constant ATTESTATIONS_REGISTRY_ID = keccak256(abi.encodePacked("Attestations")); - bytes32 constant LOCKED_GOLD_REGISTRY_ID = keccak256(abi.encodePacked("LockedGold")); - bytes32 constant GAS_CURRENCY_WHITELIST_REGISTRY_ID = keccak256( - abi.encodePacked("GasCurrencyWhitelist") - ); - bytes32 constant GOLD_TOKEN_REGISTRY_ID = keccak256(abi.encodePacked("GoldToken")); - bytes32 constant GOVERNANCE_REGISTRY_ID = keccak256(abi.encodePacked("Governance")); - bytes32 constant RESERVE_REGISTRY_ID = keccak256(abi.encodePacked("Reserve")); - bytes32 constant RANDOM_REGISTRY_ID = keccak256(abi.encodePacked("Random")); - bytes32 constant SORTED_ORACLES_REGISTRY_ID = keccak256(abi.encodePacked("SortedOracles")); - bytes32 constant VALIDATORS_REGISTRY_ID = keccak256(abi.encodePacked("Validators")); - - uint256 constant iamValidators = 1; - uint256 constant iamGoldToken = 2; - uint256 constant iamGovernance = 3; - uint256 constant iamLockedGold = 4; - - uint256 whoami; - - constructor(bool test) public RegistryHarness(test) {} - - function getAddressFor(bytes32 identifier) public returns (address) { - if (identifier == VALIDATORS_REGISTRY_ID) { - whoami = iamValidators; - } else if (identifier == GOLD_TOKEN_REGISTRY_ID) { - whoami = iamGoldToken; - } else if (identifier == GOVERNANCE_REGISTRY_ID) { - whoami = iamGovernance; - } else if (identifier == LOCKED_GOLD_REGISTRY_ID) { - whoami = iamLockedGold; - } - - // Need to statically reason that registry always returns itself now. - // In particular if can call state-modifying code through the registry (goldToken?). - return address(this); - } - - function getAddressForOrDie(bytes32 identifier) external returns (address) { - address _addr = getAddressFor(identifier); - - require(_addr != address(0), "Identifier not recognized"); - return _addr; - } - - // Local fields from other contracts are prefixed with contract name. - // Ex: contractName_fieldName - mapping(address => bool) validators_validating; - mapping(address => bool) governance_isVoting; - mapping(address => bool) validators_isVoting; - - uint256 lockedGold_totalWeight; - mapping(address => uint256) lockedGold_accountWeight; - mapping(address => address) lockedGold_accountFromVoter; - mapping(address => address) lockedGold_voterFromAccount; - mapping(address => bool) lockedGold_isVotingFrozen; - - mapping(address => uint256) goldToken_balanceOf; - - uint256 randomIndex; - mapping(uint256 => bool) randomBoolMap; - mapping(uint256 => uint256) randomUInt256Map; - mapping(uint256 => address) randomAddressMap; - - function isValidating(address account) external returns (bool) { - if (whoami == iamValidators) { - return validators_validating[account]; - } else { - return getRandomBool(); - } - } - - function isVoting(address x) external returns (bool) { - if (whoami == iamValidators) { - return validators_isVoting[x]; - } else if (whoami == iamGovernance) { - return governance_isVoting[x]; - } else { - return getRandomBool(); - } - } - - function getTotalWeight() external returns (uint256) { - if (true || whoami == iamLockedGold) { - return lockedGold_totalWeight; - } else { - return getRandomUInt256(); - } - } - - function getAccountWeight(address account) external returns (uint256) { - if (true || whoami == iamLockedGold) { - return lockedGold_accountWeight[account]; - } else { - return getRandomUInt256(); - } - } - - function getAccountFromVoter(address voter) external returns (address) { - if (true || whoami == iamLockedGold) { - return lockedGold_accountFromVoter[voter]; - } else { - return getRandomAddress(); - } - } - - function getVoterFromAccount(address account) external returns (address) { - if (true || whoami == iamLockedGold) { - return lockedGold_voterFromAccount[account]; - } else { - return getRandomAddress(); - } - } - - function isVotingFrozen(address account) external returns (bool) { - if (whoami == iamLockedGold) { - return lockedGold_isVotingFrozen[account]; - } else { - return getRandomBool(); - } - } - - function transfer(address recipient, uint256 value) external returns (bool) { - goldToken_balanceOf[msg.sender] = getRandomUInt256().sub(value); - goldToken_balanceOf[recipient] = getRandomUInt256().add(value); - return getRandomBool(); - } - - function getRandomBool() public returns (bool) { - randomIndex = randomIndex.add(1); - return randomBoolMap[randomIndex]; - } - - function getRandomUInt256() public returns (uint256) { - randomIndex = randomIndex.add(1); - return randomUInt256Map[randomIndex]; - } - - function getRandomAddress() public returns (address) { - randomIndex = randomIndex.add(1); - return randomAddressMap[randomIndex]; - } - -} diff --git a/packages/protocol/specs/harnesses/ReserveHarness.sol b/packages/protocol/specs/harnesses/ReserveHarness.sol deleted file mode 100644 index 86e43ad98..000000000 --- a/packages/protocol/specs/harnesses/ReserveHarness.sol +++ /dev/null @@ -1,15 +0,0 @@ -pragma solidity ^0.5.13; - -import "contracts/stability/Reserve.sol"; - -contract ReserveHarness is Reserve { - constructor() public Reserve(true) {} - - function contractBalance() public view returns (uint256) { - return address(this).balance; - } - - function getExchangeAddress() public view returns (address) { - return address(getExchange()); - } -} diff --git a/packages/protocol/specs/lockedGold.spec b/packages/protocol/specs/lockedGold.spec deleted file mode 100644 index 55b559b5c..000000000 --- a/packages/protocol/specs/lockedGold.spec +++ /dev/null @@ -1,194 +0,0 @@ -pragma specify 0.1 - -/** - * Example Usage: - * `certoraRun.py locked_gold.conf --path $PWD/contracts/ --cache celolockedloop3unwind --settings -patient=0,-b=3,-assumeUnwindCond` - */ - -methods { - init_state() - getNonvotingLockedGold() returns uint256 envfree - getAccountNonvotingLockedGold(address) returns uint256 envfree - ercBalanceOf(address) returns uint256 envfree - getTotalPendingWithdrawals(address) returns uint256 envfree - getPendingWithdrawalsLength(address) returns uint256 envfree - getPendingWithdrawalsIndex(address,uint256) returns uint256 envfree - getunlockingPeriod() returns uint256 envfree - incrementNonvotingAccountBalance(address, uint256) - decrementNonvotingAccountBalance(address, uint256) - unlock(uint256) - pendingWithdrawalsNotFull(address) returns bool envfree - getGoldTokenExt() returns address envfree -} - -/** - * Account's nonvoting gold cannot exceed total locked nonvoting gold. - */ -rule totalNonVotingGEAccountNonVoting(address a, method f) { - require(sinvoke getNonvotingLockedGold() >= sinvoke getAccountNonvotingLockedGold(a)); - require( - f.selector != decrementNonvotingAccountBalance(address,uint256).selector && - f.selector != incrementNonvotingAccountBalance(address,uint256).selector - ); - env eF; - require( - (f.selector != unlock(uint256).selector || eF.msg.sender == a) && - f.selector != slash(address,uint256,address,uint256,address[],address[],uint256[]).selector - ); - calldataarg arg; - sinvoke f(eF,arg); - assert(sinvoke getNonvotingLockedGold() >= sinvoke getAccountNonvotingLockedGold(a)); -} - -/** - * Total here refers to the sum of address balance and locked gold (voting and nonvoting). - */ -rule totalPreserved(address account, method f) { - // We assume the sender is not the currentContract - require(account != currentContract); - uint256 _ercBalance = sinvoke ercBalanceOf(account); - uint256 _accountNonVoting = sinvoke getAccountNonvotingLockedGold(account); - uint256 _accountTotalPendingWithdrawals = sinvoke getTotalPendingWithdrawals(account); - // We limit the amount of pending records due to loop handling - require sinvoke getPendingWithdrawalsLength(account) <= 1; - env eF; - require(eF.msg.sender == account); - // These three function are exceptions to the rule (they are designed to affect total) - require( - f.selector != decrementNonvotingAccountBalance(address,uint256).selector && - f.selector != incrementNonvotingAccountBalance(address,uint256).selector && - f.selector != slash(address,uint256,address,uint256,address[],address[],uint256[]).selector - ); - calldataarg arg; - sinvoke f(eF,arg); - // We limit the amount of pending records due to loop handling - uint length = sinvoke getPendingWithdrawalsLength(account); - require(length <= 1); - uint256 ercBalance_ = sinvoke ercBalanceOf(account); - uint256 accountNonVoting_ = sinvoke getAccountNonvotingLockedGold(account); - uint256 accountTotalPendingWithdrawals_ = sinvoke getTotalPendingWithdrawals(account); - assert( - _ercBalance + _accountNonVoting + _accountTotalPendingWithdrawals == - ercBalance_ + accountNonVoting_ + accountTotalPendingWithdrawals_, - "Total of tokens not preserved" - ); -} - -/** - * An address' total gold cannot be changed by any other contract's function calls. - */ -rule noChangeByOther(address a, address b, method f) { - require(a != b); - // We assume the sender is not the currentContract - require( - a != currentContract && - (a == sinvoke getGoldTokenExt() => f.selector != withdraw(uint256).selector)); - uint256 _ercBalance = sinvoke ercBalanceOf(a); - uint256 _accountNonVoting = sinvoke getAccountNonvotingLockedGold(a); - uint256 _accountTotalPendingWithdrawals = sinvoke getTotalPendingWithdrawals(a); - // We limit the amount of pending records due to loop handling - uint length = sinvoke getPendingWithdrawalsLength(a); - require(length <= 1); - env eF; - require(eF.msg.sender == b); - calldataarg arg; - require( - f.selector != decrementNonvotingAccountBalance(address,uint256).selector && - f.selector != incrementNonvotingAccountBalance(address,uint256).selector && - f.selector != slash(address,uint256,address,uint256,address[],address[],uint256[]).selector - ); - sinvoke f(eF,arg); - uint256 ercBalance_ = sinvoke ercBalanceOf(a); - uint256 accountNonVoting_ = sinvoke getAccountNonvotingLockedGold(a); - uint256 accountTotalPendingWithdrawals_ = sinvoke getTotalPendingWithdrawals(a); - assert(f.selector != withdraw(uint256).selector => _ercBalance == ercBalance_, "Unexpected change to erc tokens"); - assert(_accountTotalPendingWithdrawals == accountTotalPendingWithdrawals_, "Unexpected change to total pending"); - assert(_accountNonVoting == accountNonVoting_, "Unexpected change to account nonvoting"); -} - -/** - * This rule verifies the Certora Prover is correctly modeling the behavior of GoldToken._transfer. - */ -rule withdraw(uint256 index) { - env e; - uint256 _balance = sinvoke ercBalanceOf(e.msg.sender); - uint256 val = sinvoke getPendingWithdrawalsIndex(e.msg.sender, index); - sinvoke withdraw(e, index); - require (e.msg.sender != currentContract); - uint256 balance_ = sinvoke ercBalanceOf(e.msg.sender); - assert( - _balance + val == balance_, - "Withdraw balance not updated" - ); -} - -/** - * Verifies that withdraws do not occur before the unlocking period has passed. - */ -rule noWithdrawBeforeUnlocking(address account, uint256 value, method f) { - // We must make sure the length of pending withdrawals is not MAX_UINT, since then the `push` will make the length 0. - // (this should have been checked by the solidity compiler) - require(sinvoke pendingWithdrawalsNotFull(account), "Pending withdrawals are full"); - - // Unlock a value and add it to pending withdrawals - env _e; - require(_e.msg.sender == account); - sinvoke unlock(_e,value); - - // Try to run any function - adversary's goal is to succeed in unlocking before time - env eF; - require(eF.block.timestamp > _e.block.timestamp); - calldataarg arg; - sinvoke f(eF,arg); - // We check if adversary succeeded - uint256 totalPendingWithdrawals_ = sinvoke getTotalPendingWithdrawals(account); - assert( - eF.block.timestamp < _e.block.timestamp + sinvoke getunlockingPeriod() => - sinvoke getAccountNonvotingLockedGold(account) + totalPendingWithdrawals_ >= value, - "If we are before the unlock period passed, we cannot transfer the value outside the locked balance or pending balance" - ); -} - -/** - * Verifies initialization value does not change. - */ -rule only_initializer_changes_initialized_field(method f) { - env _e; - env eF; - env e_; - - bool _isInitialized = sinvoke initialized(_e); - require(f.selector != initialize(address,uint256).selector); - calldataarg arg; - invoke f(eF,arg); - bool isInitialized_ = sinvoke initialized(e_); - assert( - _isInitialized == isInitialized_, - "Method $f is not expected to change initialization field from ${_isInitialized} to ${isInitialized_}" - ); -} - -/** - * Verifies `initialize` behaves correctly: - * Reverts if already initialized, - * Sets initialized to true if not. - */ -rule check_initializer { - env _e; - env eF; - env e_; - - bool _isInitialized = sinvoke initialized(_e); - calldataarg arg; - invoke initialize(eF,arg); - bool successInit = !lastReverted; - bool isInitialized_ = sinvoke initialized(e_); - assert( - _isInitialized => !successInit, - "Initialize() must revert if already initialized" - ); - assert( - successInit => isInitialized_, - "When initialize() succeeds, must set initialization field to true" - ); -} diff --git a/packages/protocol/specs/locked_gold_linked.spec b/packages/protocol/specs/locked_gold_linked.spec deleted file mode 100644 index 1e4623daa..000000000 --- a/packages/protocol/specs/locked_gold_linked.spec +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Validators can not delegate validation while registered as validators. - */ -rule no_validate_delegation_when_validating { - env _e; - env eF; - - address account = eF.msg.sender; - bool _isAccountValidating = sinvoke _isValidating(_e,account); - - calldataarg arg; - invoke delegateValidating(eF,arg); - bool succeededDelegate = !lastReverted; - - assert( - _isAccountValidating => !succeededDelegate, - "Account successfully delegated validating even though it is already a validator" - ); -} - -/** - * Accounts can not delegate votes if already voting. - */ -rule no_vote_delegation_when_voting { - env _e; - env eF; - - address account = eF.msg.sender; - bool _isAccountVoting = sinvoke isVoting(_e,account); - - calldataarg arg; - invoke delegateVoting(eF,arg); - bool succeededDelegate = !lastReverted; - - assert( - _isAccountVoting => !succeededDelegate, - "Account successfully delegated voting even though it is already a voter" - ); -} - -/** - * Accounts can not change account weight while already voting. - */ -rule no_weight_changing_when_voting(method f, address account) { - env _e; - uint256 _accountWeight = sinvoke _weight(_e,account); - - bool isAccountVoting = sinvoke isVoting(_e,account); - - env eF; - calldataarg arg; - invoke f(eF,arg); - - env e_; - uint256 accountWeight_ = sinvoke _weight(e_,account); - - assert( - isAccountVoting => _accountWeight == accountWeight_, - "Method changed weight of account if voting" - ); -} \ No newline at end of file diff --git a/packages/protocol/specs/reserve.spec b/packages/protocol/specs/reserve.spec deleted file mode 100644 index 4ad0da117..000000000 --- a/packages/protocol/specs/reserve.spec +++ /dev/null @@ -1,29 +0,0 @@ -pragma specify 0.1 - -methods { - isSpender(address) returns bool envfree - isExchangeSpender(address) returns bool envfree - getExchangeAddress() returns address envfree - contractBalance() returns uint256 envfree -} - -rule nonspenderCantReduceBalance(address nonspender, method f) { - require(!isSpender(nonspender)); - require(!isExchangeSpender(nonspender)); - require(getExchangeAddress() != nonspender); - - uint256 balanceBefore = contractBalance(); - - env e; - require(e.msg.sender == nonspender); - calldataarg arg; - f(e, arg); - - uint256 balanceAfter = contractBalance(); - - if (f.isFallback) { - assert balanceAfter >= balanceBefore; - } else { - assert balanceAfter == balanceBefore; - } -} diff --git a/packages/protocol/specs/scripts/accounts.sh b/packages/protocol/specs/scripts/accounts.sh deleted file mode 100755 index eb8c8778b..000000000 --- a/packages/protocol/specs/scripts/accounts.sh +++ /dev/null @@ -1,7 +0,0 @@ -certoraRun specs/harnesses/AccountsHarness.sol \ - --verify AccountsHarness:specs/accounts.spec \ - --optimistic_loop \ - --loop_iter 2 \ - --cache accounts \ - --short_output \ - --msg "Accounts" diff --git a/packages/protocol/specs/scripts/accountsPrivileged.sh b/packages/protocol/specs/scripts/accountsPrivileged.sh deleted file mode 100755 index a90787813..000000000 --- a/packages/protocol/specs/scripts/accountsPrivileged.sh +++ /dev/null @@ -1,7 +0,0 @@ -certoraRun specs/harnesses/AccountsHarness.sol \ - --verify AccountsHarness:specs/accountsPrivileged.spec \ - --optimistic_loop \ - --loop_iter 2 \ - --cache accounts \ - --short_output \ - --msg "Accounts privilege check" diff --git a/packages/protocol/specs/scripts/applyHarness.sh b/packages/protocol/specs/scripts/applyHarness.sh deleted file mode 100755 index a5e375336..000000000 --- a/packages/protocol/specs/scripts/applyHarness.sh +++ /dev/null @@ -1,25 +0,0 @@ -# Private to internal to enable harnessing -perl -0777 -i -pe 's/private/internal/g' contracts/governance/Governance.sol - -# Simplify FixidityLib.multiply -perl -0777 -i -pe 's/function multiply\(Fraction memory x, Fraction memory y\) internal pure returns \(Fraction memory\) \{/ -function multiply\(Fraction memory x, Fraction memory y\) internal pure returns \(Fraction memory\) \{ - uint tmp = x.value * y.value; - require \(tmp\/x.value == y.value\); - return Fraction\(tmp \/ FIXED1_UINT\); -\} -function multiplyOld\(Fraction memory x, Fraction memory y\) private pure returns \(Fraction memory\) \{/g' contracts/common/FixidityLib.sol - -# Simplify _isProposalPassing -perl -0777 -i -pe 's/function _isProposalPassing\(Proposals.Proposal storage proposal\) internal view returns \(bool\) / - -function _isProposalPassing\(Proposals.Proposal storage proposal\) internal view returns \(bool\) { - return proposal.votes.yes > proposal.votes.no; -} - -function _isProposalPassingOld\(Proposals.Proposal storage proposal\) private view returns \(bool\)/g' contracts/governance/Governance.sol - -# Simplify Proposal's externaCall invocation to 'true' (ok because wrapped in a require, and choosing not to care about side effect - should be ECF) -perl -0777 -i -pe 's/function externalCall\(/function external_call2\(address destination, uint256 value, uint256 dataLength, bytes memory data\) private returns \(bool\) { return true; } -function external_Call\(/g' contracts/governance/Proposals.sol -perl -0777 -i -pe 's/externalCall/external_call2/g' contracts/governance/Proposals.sol diff --git a/packages/protocol/specs/scripts/governance.sh b/packages/protocol/specs/scripts/governance.sh deleted file mode 100755 index d76a81f04..000000000 --- a/packages/protocol/specs/scripts/governance.sh +++ /dev/null @@ -1,6 +0,0 @@ -certoraRun specs/harnesses/GovernanceHarness.sol contracts/common/Accounts.sol \ - --verify GovernanceHarness:specs/governance.spec \ - --cache governance \ - --optimistic_loop \ - --short_output \ - --msg "Governance" diff --git a/packages/protocol/specs/scripts/governancePrivileged.sh b/packages/protocol/specs/scripts/governancePrivileged.sh deleted file mode 100755 index 840a02457..000000000 --- a/packages/protocol/specs/scripts/governancePrivileged.sh +++ /dev/null @@ -1,6 +0,0 @@ -certoraRun specs/harnesses/GovernanceHarness.sol contracts/common/Accounts.sol \ - --verify GovernanceHarness:specs/governancePrivileged.spec \ - --cache governance \ - --optimistic_loop \ - --short_output \ - --msg "Governance privilege check" diff --git a/packages/protocol/specs/scripts/lockedgold.sh b/packages/protocol/specs/scripts/lockedgold.sh deleted file mode 100755 index edfdffd58..000000000 --- a/packages/protocol/specs/scripts/lockedgold.sh +++ /dev/null @@ -1,6 +0,0 @@ -certoraRun specs/harnesses/GoldTokenHarness.sol specs/harnesses/LockedGoldHarness.sol \ - --link LockedGoldHarness:goldToken=GoldTokenHarness \ - --verify LockedGoldHarness:specs/lockedGold.spec \ - --optimistic_loop \ - --short_output \ - --msg "LockedGold" \ diff --git a/packages/protocol/specs/scripts/reserve.sh b/packages/protocol/specs/scripts/reserve.sh deleted file mode 100755 index 317a95353..000000000 --- a/packages/protocol/specs/scripts/reserve.sh +++ /dev/null @@ -1,6 +0,0 @@ -certoraRun contracts/common/Registry.sol specs/harnesses/ReserveHarness.sol \ - --link ReserveHarness:registry=Registry \ - --verify ReserveHarness:specs/reserve.spec \ - --optimistic_loop \ - --short_output \ - --msg "Reserve" \ diff --git a/packages/protocol/test-sol/Accounts.t.sol b/packages/protocol/test-sol/Accounts.t.sol deleted file mode 100644 index 18e4495c3..000000000 --- a/packages/protocol/test-sol/Accounts.t.sol +++ /dev/null @@ -1,1531 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.5.13; -pragma experimental ABIEncoderV2; - -import "celo-foundry/Test.sol"; -import "@celo-contracts/common/FixidityLib.sol"; -import "@celo-contracts/common/Registry.sol"; -import "@celo-contracts/common/Accounts.sol"; -import "@celo-contracts/governance/test/MockValidators.sol"; - -contract AccountsTest is Test { - using FixidityLib for FixidityLib.Fraction; - - Registry registry; - Accounts accounts; - MockValidators validators; - - string constant name = "Account"; - string constant metadataURL = "https://www.celo.org"; - string constant otherMetadataURL = "https://clabs.co"; - - bytes storageRoot = abi.encodePacked(metadataURL); - bytes otherStorageRoot = abi.encodePacked(otherMetadataURL); - - bytes constant dataEncryptionKey = hex"02f2f48ee19680706196e2e339e5da3491186e0c4c5030670656b0e01611111111"; - bytes constant longDataEncryptionKey = hex"04f2f48ee19680706196e2e339e5da3491186e0c4c5030670656b0e0161111111102f2f48ee19680706196e2e339e5da3491186e0c4c5030670656b0e01611111111"; - - address caller; - uint256 callerPK; - - address caller2; - uint256 caller2PK; - - bytes32 constant EIP712DOMAIN_TYPEHASH = keccak256( - "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" - ); - - bytes32 public constant EIP712_AUTHORIZE_SIGNER_TYPEHASH = keccak256( - "AuthorizeSigner(address account,address signer,bytes32 role)" - ); - - struct Domain { - string name; - string version; - uint256 chainId; - address verifyingContract; - } - - struct AuthorizeSigner { - address account; - address signer; - bytes32 role; - } - - event AttestationSignerAuthorized(address indexed account, address signer); - event VoteSignerAuthorized(address indexed account, address signer); - event ValidatorSignerAuthorized(address indexed account, address signer); - event SignerAuthorized(address indexed account, address signer, bytes32 indexed role); - event SignerAuthorizationStarted(address indexed account, address signer, bytes32 indexed role); - event SignerAuthorizationCompleted(address indexed account, address signer, bytes32 indexed role); - event AttestationSignerRemoved(address indexed account, address oldSigner); - event VoteSignerRemoved(address indexed account, address oldSigner); - event ValidatorSignerRemoved(address indexed account, address oldSigner); - event IndexedSignerSet(address indexed account, address signer, bytes32 role); - event IndexedSignerRemoved(address indexed account, address oldSigner, bytes32 role); - event DefaultSignerSet(address indexed account, address signer, bytes32 role); - event DefaultSignerRemoved(address indexed account, address oldSigner, bytes32 role); - event LegacySignerSet(address indexed account, address signer, bytes32 role); - event LegacySignerRemoved(address indexed account, address oldSigner, bytes32 role); - event SignerRemoved(address indexed account, address oldSigner, bytes32 indexed role); - event AccountDataEncryptionKeySet(address indexed account, bytes dataEncryptionKey); - event AccountNameSet(address indexed account, string name); - event AccountMetadataURLSet(address indexed account, string metadataURL); - event AccountWalletAddressSet(address indexed account, address walletAddress); - event AccountCreated(address indexed account); - event OffchainStorageRootAdded(address indexed account, bytes url); - event OffchainStorageRootRemoved(address indexed account, bytes url, uint256 index); - event PaymentDelegationSet(address indexed beneficiary, uint256 fraction); - - function setUp() public { - address registryAddress = 0x000000000000000000000000000000000000ce10; - - deployCodeTo("Registry.sol", abi.encode(false), registryAddress); - - accounts = new Accounts(true); - validators = new MockValidators(); - - registry = Registry(registryAddress); - - registry.setAddressFor("Validators", address(validators)); - registry.setAddressFor("Accounts", address(accounts)); - - accounts.initialize(address(registry)); - accounts.setEip712DomainSeparator(); - - (caller, callerPK) = actorWithPK("caller"); - (caller2, caller2PK) = actorWithPK("caller2"); - } - - function getParsedSignatureOfAddress(address _address, uint256 privateKey) - public - pure - returns (uint8, bytes32, bytes32) - { - bytes32 addressHash = keccak256(abi.encodePacked(_address)); - bytes32 prefixedHash = ECDSA.toEthSignedMessageHash(addressHash); - return vm.sign(privateKey, prefixedHash); - } - - function assertStorageRoots( - string memory rootsHex, - uint256[] memory lengths, - string[] memory expectedRoots - ) public { - assertEq(lengths.length, expectedRoots.length); - - bytes memory roots = bytes(abi.encodePacked(rootsHex)); - uint256 currentIndex = 0; - - for (uint256 i = 0; i < expectedRoots.length; i++) { - bytes memory root = slice(roots, currentIndex, currentIndex + lengths[i]); - currentIndex += lengths[i]; - assertEq(string(root), expectedRoots[i]); - } - - assertEq(roots.length, currentIndex); - } - - function slice(bytes memory data, uint256 start, uint256 end) - internal - pure - returns (bytes memory) - { - bytes memory part = new bytes(end - start); - for (uint256 i = 0; i < part.length; i++) { - part[i] = data[i + start]; - } - return part; - } - - function getAddressFromPrivateKey(uint256 privateKey) public pure returns (address) { - return vm.addr(privateKey); - } - - function getSignatureForAuthorization( - address account, - bytes32 _role, - uint256 privateKeySigner, // This is used to simulate signing in the test environment - uint256 _chainId, - address verifyingContract - ) public pure returns (uint8 v, bytes32 r, bytes32 s) { - bytes32 dataHash = generateTypedDataHash( - Domain("Celo Core Contracts", "1.0", _chainId, verifyingContract), - AuthorizeSigner(account, getAddressFromPrivateKey(privateKeySigner), _role) - ); - - // Simulate the signing of the digest with the provided private key using the EVM function - (v, r, s) = vm.sign(privateKeySigner, dataHash); - - // Return the signature components - return (v, r, s); - } - - function generateTypedDataHash(Domain memory domain, AuthorizeSigner memory authorizeSigner) - public - pure - returns (bytes32) - { - bytes32 domainSeparator = structHashEIP712Domain(domain); - bytes32 authorizeSignerHash = getAuthorizeSigner(authorizeSigner); - return keccak256(abi.encodePacked("\x19\x01", domainSeparator, authorizeSignerHash)); - } - - function getAuthorizeSigner(AuthorizeSigner memory authorizeSigner) - public - pure - returns (bytes32) - { - return - keccak256( - abi.encode( - EIP712_AUTHORIZE_SIGNER_TYPEHASH, - authorizeSigner.account, - authorizeSigner.signer, - authorizeSigner.role - ) - ); - } - - function structHashEIP712Domain(Domain memory domain) private pure returns (bytes32) { - return - keccak256( - abi.encode( - EIP712DOMAIN_TYPEHASH, - keccak256(bytes(domain.name)), - keccak256(bytes(domain.version)), - domain.chainId, - domain.verifyingContract - ) - ); - } -} - -contract AccountsCreateAccount is AccountsTest { - function setUp() public { - super.setUp(); - } - - function test_ShouldCreateTheAccount() public { - assertEq(accounts.isAccount(address(this)), false); - accounts.createAccount(); - assertEq(accounts.isAccount(address(this)), true); - } - - function test_ShouldEmitAccountCreatedEvent() public { - vm.expectEmit(true, true, true, true); - emit AccountCreated(address(this)); - accounts.createAccount(); - } -} - -contract AccountsSetAccountDataEncryptionKey is AccountsTest { - function setUp() public { - super.setUp(); - } - - function test_ShouldSetDataEncryptionKey() public { - accounts.setAccountDataEncryptionKey(dataEncryptionKey); - assertEq(accounts.getDataEncryptionKey(address(this)), dataEncryptionKey); - } - - function test_ShouldAllowSettingAKeyWithLEadingZeros() public { - bytes memory keyWithLeadingZeros = hex"00000000000000000000000000000000000000000000000f2f48ee19680706191111"; - accounts.setAccountDataEncryptionKey(keyWithLeadingZeros); - assertEq(accounts.getDataEncryptionKey(address(this)), keyWithLeadingZeros); - } - - function test_ShouldRevertWhenKeyIsInvalid() public { - bytes memory invalidKey = hex"321329312493"; - vm.expectRevert(bytes("data encryption key length <= 32")); - accounts.setAccountDataEncryptionKey(invalidKey); - } - - function test_ShouldAllowKeyLongerThan33Bytes() public { - accounts.setAccountDataEncryptionKey(longDataEncryptionKey); - assertEq(accounts.getDataEncryptionKey(address(this)), longDataEncryptionKey); - } - - function test_ShouldEmitAccountDataEncryptionKeySet() public { - vm.expectEmit(true, true, true, true); - emit AccountDataEncryptionKeySet(address(this), dataEncryptionKey); - accounts.setAccountDataEncryptionKey(dataEncryptionKey); - } -} - -contract AccountsSetAccount is AccountsTest { - function setUp() public { - super.setUp(); - } - - function test_ShouldSetTheNameDataEncryptionKeyAndWalletAddress_WhenTheAccountHasBeenCreated() - public - { - accounts.createAccount(); - accounts.setAccount(name, dataEncryptionKey, address(this), 0, 0x0, 0x0); - assertEq(accounts.getName(address(this)), name); - assertEq(accounts.getDataEncryptionKey(address(this)), dataEncryptionKey); - assertEq(accounts.getWalletAddress(address(this)), address(this)); - } - - function test_ShouldEmitAccountNameSetEvent_WhenTheAccountHasBeenCreated() public { - accounts.createAccount(); - vm.expectEmit(true, true, true, true); - emit AccountNameSet(address(this), name); - accounts.setAccount(name, dataEncryptionKey, address(this), 0, 0x0, 0x0); - } - - function test_ShouldEmitAccountDataEncryptionKeySetEvent_WhenTheAccountHasBeenCreated() public { - accounts.createAccount(); - vm.expectEmit(true, true, true, true); - emit AccountDataEncryptionKeySet(address(this), dataEncryptionKey); - accounts.setAccount(name, dataEncryptionKey, address(this), 0, 0x0, 0x0); - } - - function test_ShouldEmitAccountWalletAddressSetEvent_WhenTheAccountHasBeenCreated() public { - accounts.createAccount(); - vm.expectEmit(true, true, true, true); - emit AccountWalletAddressSet(address(this), address(this)); - accounts.setAccount(name, dataEncryptionKey, address(this), 0, 0x0, 0x0); - } - - function test_ShouldSetADifferentAddressWithAppropriateSignature_WhenTheAccountHasBeenCreated() - public - { - (uint8 v, bytes32 r, bytes32 s) = getParsedSignatureOfAddress(address(this), caller2PK); - accounts.setAccount(name, dataEncryptionKey, caller2, v, r, s); - assertEq(accounts.getWalletAddress(address(this)), caller2); - } - - function test_ShouldSetTheNameDataEncryptionKeyAndWalletAddress_WhenTheAccountHasNotBeenCreated() - public - { - accounts.setAccount(name, dataEncryptionKey, address(this), 0, 0x0, 0x0); - assertEq(accounts.getName(address(this)), name); - assertEq(accounts.getDataEncryptionKey(address(this)), dataEncryptionKey); - assertEq(accounts.getWalletAddress(address(this)), address(this)); - assertEq(accounts.isAccount(address(this)), true); - } - - function test_ShouldEmitAccountCreated_WhenTheAccountHasNotBeenCreated() public { - vm.expectEmit(true, true, true, true); - emit AccountCreated(address(this)); - accounts.setAccount(name, dataEncryptionKey, address(this), 0, 0x0, 0x0); - } - - function test_ShouldEmitAccountNameSetEvent_WhenTheAccountHasNotBeenCreated() public { - vm.expectEmit(true, true, true, true); - emit AccountNameSet(address(this), name); - accounts.setAccount(name, dataEncryptionKey, address(this), 0, 0x0, 0x0); - } - - function test_ShouldEmitAccountDataEncryptionKeySetEvent_WhenTheAccountHasNotBeenCreated() - public - { - vm.expectEmit(true, true, true, true); - emit AccountDataEncryptionKeySet(address(this), dataEncryptionKey); - accounts.setAccount(name, dataEncryptionKey, address(this), 0, 0x0, 0x0); - } - - function test_ShouldEmitAccountWalletAddressSetEvent_WhenTheAccountHasNotBeenCreated() public { - vm.expectEmit(true, true, true, true); - emit AccountWalletAddressSet(address(this), address(this)); - accounts.setAccount(name, dataEncryptionKey, address(this), 0, 0x0, 0x0); - } - - function test_ShouldRevertWhenIncorrectSignature() public { - (uint8 v, bytes32 r, bytes32 s) = getParsedSignatureOfAddress(address(caller), caller2PK); - vm.prank(caller); - vm.expectRevert("Invalid signature"); - accounts.setAccount(name, dataEncryptionKey, address(this), v, r, s); - } -} - -contract AccountsSetWalletAddress is AccountsTest { - function setUp() public { - super.setUp(); - } - - function test_ShouldRevert_WhenAccountHasNotBeenCreated() public { - vm.expectRevert("Unknown account"); - accounts.setWalletAddress(address(this), 0, 0x0, 0x0); - } - - function test_ShouldSetWalletAddress_WhenAccountHasBeenCreated() public { - accounts.createAccount(); - accounts.setWalletAddress(address(this), 0, 0x0, 0x0); - assertEq(accounts.getWalletAddress(address(this)), address(this)); - } - - function test_ShouldSetDifferentAddressWithTheAppropriateSignature_WhenAccountHasBeenCreated() - public - { - vm.startPrank(caller); - accounts.createAccount(); - (uint8 v, bytes32 r, bytes32 s) = getParsedSignatureOfAddress(address(caller), caller2PK); - accounts.setWalletAddress(caller2, v, r, s); - assertEq(accounts.getWalletAddress(address(caller)), caller2); - } - - function test_ShouldSetTheNULLAddress_WhenAccountHasBeenCreated() public { - accounts.createAccount(); - accounts.setWalletAddress(address(0), 0, 0x0, 0x0); - assertEq(accounts.getWalletAddress(address(this)), address(0)); - } - - function test_ShouldEmitTheAccountWalletAddressSetEvent_WhenAccountHasBeenCreated() public { - accounts.createAccount(); - vm.expectEmit(true, true, true, true); - emit AccountWalletAddressSet(address(this), address(this)); - accounts.setWalletAddress(address(this), 0, 0x0, 0x0); - } - - function test_ShouldRevertWithWrongSignatureForADifferentAddress_WhenAccountHasBEenCreated() - public - { - vm.startPrank(caller); - accounts.createAccount(); - (uint8 v, bytes32 r, bytes32 s) = getParsedSignatureOfAddress(address(caller), caller2PK); - vm.expectRevert("Invalid signature"); - accounts.setWalletAddress(address(this), v, r, s); - } -} - -contract AccountsSetMetadataURL is AccountsTest { - function setUp() public { - super.setUp(); - } - - function test_ShouldRevert_WhenAccountHasNotBeenCreated() public { - vm.expectRevert("Unknown account"); - accounts.setMetadataURL(metadataURL); - } - - function test_ShouldSetMetadatURL_WhenAccountHasBeenCreated() public { - accounts.createAccount(); - accounts.setMetadataURL(metadataURL); - assertEq(accounts.getMetadataURL(address(this)), metadataURL); - } - - function test_ShouldEmitTheAccountMetadataURLSetEvent() public { - accounts.createAccount(); - vm.expectEmit(true, true, true, true); - emit AccountMetadataURLSet(address(this), metadataURL); - accounts.setMetadataURL(metadataURL); - } -} - -contract AccountsBatchGetMetadataURL is AccountsTest { - function setUp() public { - super.setUp(); - } - - function parseSolidityStringArray(uint256[] memory stringLengths, bytes memory data) - private - pure - returns (string[] memory) - { - string[] memory strings = new string[](stringLengths.length); - uint256 offset = 0; - - for (uint256 i = 0; i < stringLengths.length; i++) { - bytes memory stringBytes = new bytes(stringLengths[i]); - for (uint256 j = 0; j < stringLengths[i]; j++) { - stringBytes[j] = data[offset + j]; - } - strings[i] = string(stringBytes); - offset += stringLengths[i]; - } - - return strings; - } - - function test_ShouldReturnTheMetadataURLs() public { - accounts.createAccount(); - accounts.setMetadataURL(metadataURL); - vm.prank(caller2); - accounts.createAccount(); - vm.prank(caller2); - accounts.setMetadataURL(otherMetadataURL); - - address[] memory addresses = new address[](2); - addresses[0] = address(this); - addresses[1] = address(caller2); - - string[] memory urlStrings = new string[](2); - urlStrings[0] = metadataURL; - urlStrings[1] = otherMetadataURL; - - (uint256[] memory sizes, bytes memory data) = accounts.batchGetMetadataURL(addresses); - - string[] memory returnedStrings = parseSolidityStringArray(sizes, data); - - for (uint256 i = 0; i < returnedStrings.length; i++) { - assertEq(returnedStrings[i], urlStrings[i]); - } - } -} - -contract AccountsAddStorageRoot is AccountsTest { - function setUp() public { - super.setUp(); - } - - function test_ShouldRevert_WhenAccountHasNotBeenCreated() public { - vm.expectRevert("Unknown account"); - accounts.addStorageRoot(storageRoot); - } - - function test_ShouldAddANewStorageRoot_WhenAccountHasBeenCreated() public { - accounts.createAccount(); - accounts.addStorageRoot(bytes(storageRoot)); - (bytes memory concatenated, uint256[] memory length) = accounts.getOffchainStorageRoots( - address(this) - ); - - string[] memory urls = new string[](1); - urls[0] = metadataURL; - - assertStorageRoots(string(concatenated), length, urls); - } - - function test_ShouldEmitTheOffchainStorageRootAddedEvent_WhenAccountHasBeenCreated() public { - accounts.createAccount(); - vm.expectEmit(true, true, true, true); - emit OffchainStorageRootAdded(address(this), bytes(metadataURL)); - accounts.addStorageRoot(bytes(metadataURL)); - } - - function test_ShouldAddMultipleStorageRoots_WhenAccountHasBeenCreated() public { - accounts.createAccount(); - accounts.addStorageRoot(bytes(metadataURL)); - accounts.addStorageRoot(bytes(otherMetadataURL)); - (bytes memory concatenated, uint256[] memory length) = accounts.getOffchainStorageRoots( - address(this) - ); - - string[] memory urls = new string[](2); - urls[0] = metadataURL; - urls[1] = otherMetadataURL; - - assertStorageRoots(string(concatenated), length, urls); - } -} - -contract AccountsRemoveStorageRoot is AccountsTest { - function setUp() public { - super.setUp(); - } - - function test_ShouldRevert_WhenAccountHasNotBeenCreated() public { - vm.expectRevert("Unknown account"); - accounts.removeStorageRoot(0); - } - - function test_ShouldRevertWithMessage_WhenThereAreNoStorageRootsAndAccountHasBeenCreated() - public - { - accounts.createAccount(); - vm.expectRevert("Invalid storage root index"); - accounts.removeStorageRoot(0); - } - - function test_ShouldRemoveOneOfTheRoots_WhenThereAreStorageRootsAndAccountHasBeenCreated() - public - { - accounts.createAccount(); - accounts.addStorageRoot(storageRoot); - accounts.addStorageRoot(otherStorageRoot); - accounts.removeStorageRoot(0); - - (bytes memory concatenated, uint256[] memory length) = accounts.getOffchainStorageRoots( - address(this) - ); - - string[] memory urls = new string[](1); - urls[0] = otherMetadataURL; - - assertStorageRoots(string(concatenated), length, urls); - } - - function test_ShouldRemoveDifferentRoot_WhenThereAreStorageRootsAndAccountHasBeenCreated() - public - { - accounts.createAccount(); - accounts.addStorageRoot(storageRoot); - accounts.addStorageRoot(otherStorageRoot); - accounts.removeStorageRoot(1); - - (bytes memory concatenated, uint256[] memory length) = accounts.getOffchainStorageRoots( - address(this) - ); - - string[] memory urls = new string[](1); - urls[0] = metadataURL; - - assertStorageRoots(string(concatenated), length, urls); - } - - function test_ShouldEmitOffchainStorageRootRemovedEvent_WhenThereAreStorageRootsAndAccountHasBeenCreated() - public - { - accounts.createAccount(); - accounts.addStorageRoot(storageRoot); - accounts.addStorageRoot(otherStorageRoot); - - vm.expectEmit(true, true, true, true); - emit OffchainStorageRootRemoved(address(this), bytes(otherMetadataURL), 1); - accounts.removeStorageRoot(1); - - (bytes memory concatenated, uint256[] memory length) = accounts.getOffchainStorageRoots( - address(this) - ); - - string[] memory urls = new string[](1); - urls[0] = metadataURL; - - assertStorageRoots(string(concatenated), length, urls); - } -} - -contract AccountsSetPaymentDelegation is AccountsTest { - address beneficiary = actor("beneficiary"); - uint256 fraction = FixidityLib.newFixedFraction(2, 10).unwrap(); - uint256 badFraction = FixidityLib.newFixedFraction(12, 10).unwrap(); - - function setUp() public { - super.setUp(); - } - - function test_ShouldNotBeCallableByNonAccount() public { - vm.expectRevert("Must first register address with Account.createAccount"); - accounts.setPaymentDelegation((beneficiary), fraction); - } - - function test_ShouldSetAnAddressAndAFraction() public { - accounts.createAccount(); - accounts.setPaymentDelegation(beneficiary, fraction); - (address realBeneficiary, uint256 realFraction) = accounts.getPaymentDelegation(address(this)); - assertEq(realBeneficiary, beneficiary); - assertEq(realFraction, fraction); - } - - function test_ShouldNotAllowFractionGreaterThan1() public { - accounts.createAccount(); - vm.expectRevert("Fraction must not be greater than 1"); - accounts.setPaymentDelegation(beneficiary, badFraction); - } - - function test_ShouldNotAllowABeneficiaryWithNullAddress() public { - accounts.createAccount(); - vm.expectRevert("Beneficiary cannot be address 0x0"); - accounts.setPaymentDelegation(address(0), badFraction); - } - - function test_ShouldEmitAPaymentDelegationSetEvent() public { - accounts.createAccount(); - vm.expectEmit(true, true, true, true); - emit PaymentDelegationSet(beneficiary, fraction); - accounts.setPaymentDelegation(beneficiary, fraction); - } -} - -contract AccountsDeletePaymentDelegation is AccountsTest { - address beneficiary = actor("beneficiary"); - uint256 fraction = FixidityLib.newFixedFraction(2, 10).unwrap(); - - function setUp() public { - super.setUp(); - accounts.createAccount(); - accounts.setPaymentDelegation(beneficiary, fraction); - } - - function test_ShouldNotBeCallableByNonAccount() public { - vm.prank(caller); - vm.expectRevert("Must first register address with Account.createAccount"); - accounts.deletePaymentDelegation(); - } - - function test_ShouldSetTheAddressAndBeneficiaryTo0() public { - accounts.deletePaymentDelegation(); - (address realBeneficiary, uint256 realFraction) = accounts.getPaymentDelegation(address(this)); - assertEq(realBeneficiary, address(0)); - assertEq(realFraction, 0); - } - - function test_ShouldEmitAPaymentDelegationSetEvent() public { - vm.expectEmit(true, true, true, true); - emit PaymentDelegationSet(address(0), 0); - accounts.deletePaymentDelegation(); - } -} - -contract AccountsSetName is AccountsTest { - function setUp() public { - super.setUp(); - } - - function test_ShouldNotBeCallableByNonAccount() public { - vm.expectRevert("Register with createAccount to set account name"); - accounts.setName(name); - } - - function test_ShouldSetTheName() public { - accounts.createAccount(); - accounts.setName(name); - assertEq(accounts.getName(address(this)), name); - } - - function test_ShouldEmitAccountNameSetEvent() public { - accounts.createAccount(); - vm.expectEmit(true, true, true, true); - emit AccountNameSet(address(this), name); - accounts.setName(name); - } -} - -contract AccountsGenericAuthorization is AccountsTest { - address account2 = actor("account2"); - address signer; - uint256 signerPK; - address signer2; - uint256 signer2PK; - bytes32 role = keccak256("Test Role"); - bytes32 role2 = keccak256("Test Role 2"); - - uint8 v; - bytes32 r; - bytes32 s; - - function setUp() public { - super.setUp(); - (signer, signerPK) = actorWithPK("signer"); - (signer2, signer2PK) = actorWithPK("signer2"); - (v, r, s) = getSignatureForAuthorization( - address(this), - role, - signerPK, - 31337, - address(accounts) - ); - accounts.createAccount(); - vm.prank(account2); - accounts.createAccount(); - } - - function test_ShouldRecoverTheCorrectSignerFromEIP712Signature() public { - address recoveredSigner = accounts.getRoleAuthorizationSigner( - address(this), - signer, - role, - v, - r, - s - ); - assertEq(recoveredSigner, signer); - } - - function test_ShouldNotCompleteAnAuthorizationThatHasntBeenStarted_WhenSmartContractSigner() - public - { - vm.expectRevert("Signer authorization not started"); - vm.prank(signer); - accounts.completeSignerAuthorization(address(this), role); - } - - function test_ShouldNotCompleteAuthorizationThatWasOnlyStarted_WhenSmartContractSigner() public { - accounts.authorizeSigner(signer, role); - assertEq(accounts.isSigner(address(this), signer, role), false); - } - - function test_ShouldSetAuthorizedSignerInTwoSteps_WhenSmartContractSigner() public { - accounts.authorizeSigner(signer, role); - vm.prank(signer); - accounts.completeSignerAuthorization(address(this), role); - assertEq(accounts.isSigner(address(this), signer, role), true); - assertEq(accounts.authorizedBy(signer), address(this)); - assertEq(accounts.isAuthorizedSigner(signer), true); - } - - function test_ShouldEmitTheRightEvents_WhenSmartContractSigner() public { - vm.expectEmit(true, true, true, true); - emit SignerAuthorizationStarted(address(this), signer, role); - accounts.authorizeSigner(signer, role); - vm.expectEmit(true, true, true, true); - emit SignerAuthorizationCompleted(address(this), signer, role); - vm.prank(signer); - accounts.completeSignerAuthorization(address(this), role); - } - - function test_ShouldSetAuthorizedSignerInOneStep_WhenEOASigner() public { - assertEq(accounts.isSigner(address(this), signer, role), false); - accounts.authorizeSignerWithSignature(signer, role, v, r, s); - - assertEq(accounts.isSigner(address(this), signer, role), true); - assertEq(accounts.authorizedBy(signer), address(this)); - assertEq(accounts.isAuthorizedSigner(signer), true); - } - - function test_ShouldEmitTheRightEvents_WhenEOASigner() public { - vm.expectEmit(true, true, true, true); - emit SignerAuthorized(address(this), signer, role); - accounts.authorizeSignerWithSignature(signer, role, v, r, s); - } - - function test_ShouldRemoveTheAuthorizedSigner() public { - accounts.authorizeSignerWithSignature(signer, role, v, r, s); - accounts.removeSigner(signer, role); - assertEq(accounts.isSigner(address(this), signer, role), false); - } - - function test_ShouldAuthorizeMultipleSignersForARole() public { - assertEq(accounts.isSigner(address(this), signer, role), false); - assertEq(accounts.isSigner(address(this), signer2, role), false); - - accounts.authorizeSignerWithSignature(signer, role, v, r, s); - - (uint8 v2, bytes32 r2, bytes32 s2) = getSignatureForAuthorization( - address(this), - role, - signer2PK, - 31337, - address(accounts) - ); - - accounts.authorizeSignerWithSignature(signer2, role, v2, r2, s2); - - assertEq(accounts.isSigner(address(this), signer, role), true); - assertEq(accounts.isSigner(address(this), signer2, role), true); - assertEq(accounts.authorizedBy(signer), address(this)); - assertEq(accounts.authorizedBy(signer2), address(this)); - assertEq(accounts.isAuthorizedSigner(signer), true); - assertEq(accounts.isAuthorizedSigner(signer2), true); - } - - function test_ShouldAuthorizeMultipleSignersForMultipleRoles() public { - assertEq(accounts.isSigner(address(this), signer, role), false); - assertEq(accounts.isSigner(address(this), signer2, role2), false); - - accounts.authorizeSignerWithSignature(signer, role, v, r, s); - - (uint8 v2, bytes32 r2, bytes32 s2) = getSignatureForAuthorization( - address(this), - role2, - signer2PK, - 31337, - address(accounts) - ); - - accounts.authorizeSignerWithSignature(signer2, role2, v2, r2, s2); - - assertEq(accounts.isSigner(address(this), signer, role), true); - assertEq(accounts.isSigner(address(this), signer2, role2), true); - assertEq(accounts.authorizedBy(signer), address(this)); - assertEq(accounts.authorizedBy(signer2), address(this)); - assertEq(accounts.isAuthorizedSigner(signer), true); - assertEq(accounts.isAuthorizedSigner(signer2), true); - } - - function test_ShouldNotAllowToAuthorizeSignerForTwoAccounts() public { - accounts.authorizeSignerWithSignature(signer, role, v, r, s); - - (uint8 v2, bytes32 r2, bytes32 s2) = getSignatureForAuthorization( - account2, - role, - signerPK, - 31337, - address(accounts) - ); - - vm.expectRevert("Invalid signature"); - accounts.authorizeSignerWithSignature(signer, role, v2, r2, s2); - } - - function test_ShouldSetDefaultSignerForTheRole() public { - assertEq(accounts.isSigner(address(this), signer, role), false); - assertEq(accounts.hasDefaultSigner(address(this), role), false); - assertEq(accounts.getDefaultSigner(address(this), role), address(this)); - - vm.expectRevert("Must authorize signer before setting as default"); - accounts.setIndexedSigner(signer, role); - - accounts.authorizeSignerWithSignature(signer, role, v, r, s); - accounts.setIndexedSigner(signer, role); - - assertEq(accounts.isSigner(address(this), signer, role), true); - assertEq(accounts.hasDefaultSigner(address(this), role), true); - assertEq(accounts.getDefaultSigner(address(this), role), signer); - } - - function test_ShouldRemoveTheDefaultSignerForARole() public { - accounts.authorizeSignerWithSignature(signer, role, v, r, s); - accounts.setIndexedSigner(signer, role); - accounts.removeDefaultSigner(role); - - assertEq(accounts.isSigner(address(this), signer, role), true); - assertEq(accounts.hasDefaultSigner(address(this), role), false); - assertEq(accounts.getDefaultSigner(address(this), role), address(this)); - } -} - -contract AccountsBackwardCompatibility is AccountsTest { - address account = address(this); - address otherAccount = actor("otherAccount"); - - address signer; - uint256 signerPK; - address signer2; - uint256 signer2PK; - - enum Role { Attestation, Vote, Validator } - - function setUp() public { - super.setUp(); - - (signer, signerPK) = actorWithPK("signer"); - (signer2, signer2PK) = actorWithPK("signer2"); - - accounts.createAccount(); - } - - function authorizeSignerFactory( - address _signer, - bytes32 _role, - uint8 _v, - bytes32 _r, - bytes32 _s, - bool expectRevert - ) public { - accounts.authorizeSignerWithSignature(_signer, _role, _v, _r, _s); - if (!expectRevert) { - accounts.setIndexedSigner(_signer, _role); - } - } - - function getSignature(address _account, bytes32 role, uint256 _signerPK, bool genericWrite) - public - view - returns (uint8, bytes32, bytes32) - { - if (genericWrite) { - return getSignatureForAuthorization(_account, role, _signerPK, 31337, address(accounts)); - } - - return getParsedSignatureOfAddress(_account, _signerPK); - } - - function getRole(Role role) public pure returns (bytes32 _role) { - if (role == Role.Attestation) { - _role = keccak256(abi.encodePacked("celo.org/core/attestation")); - } else if (role == Role.Vote) { - _role = keccak256(abi.encodePacked("celo.org/core/vote")); - } else if (role == Role.Validator) { - _role = keccak256(abi.encodePacked("celo.org/core/validator")); - } - } - - function hasAuthorizedSigner(Role role, address _signer, bool genericRead) - public - view - returns (bool) - { - bytes32 _role = getRole(role); - if (genericRead) { - return accounts.hasIndexedSigner(_signer, _role); - } else { - if (role == Role.Attestation) { - return accounts.hasAuthorizedAttestationSigner(_signer); - } else if (role == Role.Vote) { - return accounts.hasAuthorizedVoteSigner(_signer); - } else if (role == Role.Validator) { - return accounts.hasAuthorizedValidatorSigner(_signer); - } - } - } - - function authorize( - Role role, - bool genericWrite, - address _account, - address _signer, - uint256 _signerPK - ) public { - bytes32 _role = getRole(role); - (uint8 _v, bytes32 _r, bytes32 _s) = getSignature(_account, _role, _signerPK, genericWrite); - vm.startPrank(_account); - if (genericWrite) { - authorizeSignerFactory(_signer, _role, _v, _r, _s, false); - } else { - if (role == Role.Attestation) { - accounts.authorizeAttestationSigner(_signer, _v, _r, _s); - } else if (role == Role.Vote) { - accounts.authorizeVoteSigner(_signer, _v, _r, _s); - } else if (role == Role.Validator) { - accounts.authorizeValidatorSigner(_signer, _v, _r, _s); - } - } - vm.stopPrank(); - } - - function removeSigner(bool genericWrite, Role role, address _account) public { - vm.startPrank(_account); - bytes32 _role = getRole(role); - if (genericWrite) { - address defaultSigner = accounts.getIndexedSigner(_account, _role); - accounts.removeSigner(defaultSigner, _role); - } else { - if (role == Role.Attestation) { - accounts.removeAttestationSigner(); - } else if (role == Role.Vote) { - accounts.removeVoteSigner(); - } else if (role == Role.Validator) { - accounts.removeValidatorSigner(); - } - } - vm.stopPrank(); - } - - function getAuthorizedFromAccount(Role role, bool genericRead, address _account) - public - view - returns (address) - { - bytes32 _role = getRole(role); - if (genericRead) { - return accounts.getIndexedSigner(_account, _role); - } else { - if (role == Role.Attestation) { - return accounts.getAttestationSigner(_account); - } else if (role == Role.Vote) { - return accounts.getVoteSigner(_account); - } else if (role == Role.Validator) { - return accounts.getValidatorSigner(_account); - } - } - } - - function authorizedSignerToAccount(Role role, bool genericRead, address _signer) - public - view - returns (address) - { - if (genericRead) { - return accounts.signerToAccount(_signer); - } else { - if (role == Role.Attestation) { - return accounts.attestationSignerToAccount(_signer); - } else if (role == Role.Vote) { - return accounts.voteSignerToAccount(_signer); - } else if (role == Role.Validator) { - return accounts.validatorSignerToAccount(_signer); - } - } - } - - function helperShouldSetAuthorizedKey(bool genericRead, bool genericWrite, Role role) public { - assertEq(hasAuthorizedSigner(role, account, genericRead), false); - authorize(role, genericWrite, account, signer, signerPK); - assertEq(accounts.authorizedBy(signer), account); - assertEq(getAuthorizedFromAccount(role, genericRead, account), signer); - assertEq(authorizedSignerToAccount(role, genericRead, signer), account); - assertEq(hasAuthorizedSigner(role, account, genericRead), true); - } - - function test_ShouldAuthorizeVoteSigningKey_GenericReadFalse_GenericWriteFalse() public { - helperShouldSetAuthorizedKey(false, false, Role.Vote); - } - - function test_ShouldAuthorizeVoteSigningKey_GenericReadFalse_GenericWriteTrue() public { - helperShouldSetAuthorizedKey(false, true, Role.Vote); - } - - function test_ShouldAuthorizeVoteSigningKey_GenericReadTrue_GenericWriteFalse() public { - helperShouldSetAuthorizedKey(true, false, Role.Vote); - } - - function test_ShouldAuthorizeVoteSigningKey_GenericReadTrue_GenericWriteTrue() public { - helperShouldSetAuthorizedKey(true, true, Role.Vote); - } - - function test_ShouldAuthorizeAttestationSigningKey_GenericReadFalse_GenericWriteFalse() public { - helperShouldSetAuthorizedKey(false, false, Role.Attestation); - } - - function test_ShouldAuthorizeAttestationSigningKey_GenericReadFalse_GenericWriteTrue() public { - helperShouldSetAuthorizedKey(false, true, Role.Attestation); - } - - function test_ShouldAuthorizeAttestationSigningKey_GenericReadTrue_GenericWriteFalse() public { - helperShouldSetAuthorizedKey(true, false, Role.Attestation); - } - - function test_ShouldAuthorizeAttestationSigningKey_GenericReadTrue_GenericWriteTrue() public { - helperShouldSetAuthorizedKey(true, true, Role.Attestation); - } - - function test_ShouldAuthorizeValidatorSigningKey_GenericReadFalse_GenericWriteFalse() public { - helperShouldSetAuthorizedKey(false, false, Role.Validator); - } - - function test_ShouldAuthorizeValidatorSigningKey_GenericReadFalse_GenericWriteTrue() public { - helperShouldSetAuthorizedKey(false, true, Role.Validator); - } - - function test_ShouldAuthorizeValidatorSigningKey_GenericReadTrue_GenericWriteFalse() public { - helperShouldSetAuthorizedKey(true, false, Role.Validator); - } - - function test_ShouldAuthorizeValidatorSigningKey_GenericReadTrue_GenericWriteTrue() public { - helperShouldSetAuthorizedKey(true, true, Role.Validator); - } - - function test_ShouldEmitRightEventVote_GenericWriteTrue() public { - vm.expectEmit(true, true, true, true); - emit SignerAuthorized(account, signer, getRole(Role.Vote)); - authorize(Role.Vote, true, account, signer, signerPK); - } - - function test_ShouldEmitRightEventVote_GenericWriteFalse() public { - vm.expectEmit(true, true, true, true); - emit VoteSignerAuthorized(account, signer); - authorize(Role.Vote, false, account, signer, signerPK); - } - - function test_ShouldEmitRightEventAttestation_GenericWriteTrue() public { - vm.expectEmit(true, true, true, true); - emit SignerAuthorized(account, signer, getRole(Role.Attestation)); - authorize(Role.Attestation, true, account, signer, signerPK); - } - - function test_ShouldEmitRightEventAttestation_GenericWriteFalse() public { - vm.expectEmit(true, true, true, true); - emit AttestationSignerAuthorized(account, signer); - authorize(Role.Attestation, false, account, signer, signerPK); - } - - function test_ShouldEmitRightEventValidator_GenericWriteTrue() public { - vm.expectEmit(true, true, true, true); - emit SignerAuthorized(account, signer, getRole(Role.Validator)); - authorize(Role.Validator, true, account, signer, signerPK); - } - - function test_ShouldEmitRightEventValidator_GenericWriteFalse() public { - vm.expectEmit(true, true, true, true); - emit ValidatorSignerAuthorized(account, signer); - authorize(Role.Validator, false, account, signer, signerPK); - } - - function test_ShouldRevertIfVoteIsAnAccount_GenericWriteTrue() public { - vm.prank(signer); - accounts.createAccount(); - vm.expectRevert("Cannot re-authorize address or locked gold account for another account"); - bytes32 _role = getRole(Role.Vote); - (uint8 _v, bytes32 _r, bytes32 _s) = getSignature(account, _role, signerPK, true); - authorizeSignerFactory(signer, _role, _v, _r, _s, true); - } - - function test_ShouldRevertIfVoteIsAnAccount_GenericWriteFalse() public { - vm.prank(signer); - accounts.createAccount(); - vm.expectRevert("Cannot re-authorize address or locked gold account for another account"); - authorize(Role.Vote, false, account, signer, signerPK); - } - - function test_ShouldRevertIfValidatorIsAnAccount_GenericWriteTrue() public { - vm.prank(signer); - accounts.createAccount(); - vm.expectRevert("Cannot re-authorize address or locked gold account for another account"); - bytes32 _role = getRole(Role.Validator); - (uint8 _v, bytes32 _r, bytes32 _s) = getSignature(account, _role, signerPK, true); - authorizeSignerFactory(signer, _role, _v, _r, _s, true); - } - - function test_ShouldRevertIfValidatorIsAnAccount_GenericWriteFalse() public { - vm.prank(signer); - accounts.createAccount(); - vm.expectRevert("Cannot re-authorize address or locked gold account for another account"); - authorize(Role.Validator, false, account, signer, signerPK); - } - - function test_ShouldRevertIfAttestationIsAnAccount_GenericWriteTrue() public { - vm.prank(signer); - accounts.createAccount(); - vm.expectRevert("Cannot re-authorize address or locked gold account for another account"); - bytes32 _role = getRole(Role.Attestation); - (uint8 _v, bytes32 _r, bytes32 _s) = getSignature(account, _role, signerPK, true); - authorizeSignerFactory(signer, _role, _v, _r, _s, true); - } - - function test_ShouldRevertIfAttestationIsAnAccount_GenericWriteFalse() public { - vm.prank(signer); - accounts.createAccount(); - vm.expectRevert("Cannot re-authorize address or locked gold account for another account"); - authorize(Role.Attestation, false, account, signer, signerPK); - } - - function test_ShouldRevertIfVoteIsAlreadyAuthorized_GenericWriteFalse() public { - vm.prank(otherAccount); - accounts.createAccount(); - authorize(Role.Vote, true, otherAccount, signer, signerPK); - vm.expectRevert("Cannot re-authorize address or locked gold account for another account"); - - authorize(Role.Vote, false, account, signer, signerPK); - } - - function test_ShouldRevertIfVoteIsAlreadyAuthorized_GenericWriteTrue() public { - vm.prank(otherAccount); - accounts.createAccount(); - authorize(Role.Vote, true, otherAccount, signer, signerPK); - vm.expectRevert("Cannot re-authorize address or locked gold account for another account"); - bytes32 _role = getRole(Role.Vote); - (uint8 _v, bytes32 _r, bytes32 _s) = getSignature(account, _role, signerPK, true); - authorizeSignerFactory(signer, _role, _v, _r, _s, true); - } - - function test_ShouldRevertIfValidatorIsAlreadyAuthorized_GenericWriteFalse() public { - vm.prank(otherAccount); - accounts.createAccount(); - authorize(Role.Validator, true, otherAccount, signer, signerPK); - vm.expectRevert("Cannot re-authorize address or locked gold account for another account"); - - authorize(Role.Validator, false, account, signer, signerPK); - } - - function test_ShouldRevertIfValidatorIsAlreadyAuthorized_GenericWriteTrue() public { - vm.prank(otherAccount); - accounts.createAccount(); - authorize(Role.Validator, true, otherAccount, signer, signerPK); - vm.expectRevert("Cannot re-authorize address or locked gold account for another account"); - bytes32 _role = getRole(Role.Validator); - (uint8 _v, bytes32 _r, bytes32 _s) = getSignature(account, _role, signerPK, true); - authorizeSignerFactory(signer, _role, _v, _r, _s, true); - } - - function test_ShouldRevertIfAttestationIsAlreadyAuthorized_GenericWriteFalse() public { - vm.prank(otherAccount); - accounts.createAccount(); - authorize(Role.Attestation, true, otherAccount, signer, signerPK); - vm.expectRevert("Cannot re-authorize address or locked gold account for another account"); - - authorize(Role.Attestation, false, account, signer, signerPK); - } - - function test_ShouldRevertIfAttestationIsAlreadyAuthorized_GenericWriteTrue() public { - vm.prank(otherAccount); - accounts.createAccount(); - authorize(Role.Attestation, true, otherAccount, signer, signerPK); - vm.expectRevert("Cannot re-authorize address or locked gold account for another account"); - bytes32 _role = getRole(Role.Attestation); - (uint8 _v, bytes32 _r, bytes32 _s) = getSignature(account, _role, signerPK, true); - authorizeSignerFactory(signer, _role, _v, _r, _s, true); - } - - function helperShouldRevertIfSignatureIsIncorrect(Role role, bool genericWrite) public { - (, uint256 otherSignerPK) = actorWithPK("otherSigner"); - bytes32 _role = getRole(role); - (uint8 v, bytes32 r, bytes32 s) = getSignature(account, _role, otherSignerPK, genericWrite); - vm.expectRevert("Invalid signature"); - authorizeSignerFactory(signer, _role, v, r, s, true); - } - - function test_ShouldRevertIfSignatureIsIncorrect_Attestations_GenericWriteTrue() public { - helperShouldRevertIfSignatureIsIncorrect(Role.Attestation, true); - } - - function test_ShouldRevertIfSignatureIsIncorrect_Attestations_GenericWriteFalse() public { - helperShouldRevertIfSignatureIsIncorrect(Role.Attestation, false); - } - - function test_ShouldRevertIfSignatureIsIncorrect_Vote_GenericWriteTrue() public { - helperShouldRevertIfSignatureIsIncorrect(Role.Vote, true); - } - - function test_ShouldRevertIfSignatureIsIncorrect_Vote_GenericWriteFalse() public { - helperShouldRevertIfSignatureIsIncorrect(Role.Vote, false); - } - - function test_ShouldRevertIfSignatureIsIncorrect_Validator_GenericWriteTrue() public { - helperShouldRevertIfSignatureIsIncorrect(Role.Validator, true); - } - - function test_ShouldRevertIfSignatureIsIncorrect_Validator_GenericWriteFalse() public { - helperShouldRevertIfSignatureIsIncorrect(Role.Validator, false); - } - - function helperShouldSetTheNewAuthorized(Role role, bool genericWrite, bool genericRead) public { - authorize(role, genericWrite, account, signer, signerPK); - (address newAuthorized, uint256 newAuthorizedPK) = actorWithPK("otherSigner"); - authorize(role, genericWrite, account, newAuthorized, newAuthorizedPK); - - assertEq(accounts.authorizedBy(newAuthorized), account); - assertEq(getAuthorizedFromAccount(role, genericRead, account), newAuthorized); - assertEq(authorizedSignerToAccount(role, genericRead, newAuthorized), account); - assertEq(accounts.authorizedBy(signer), account); - } - - function test_ShouldSetTheNewAuthorized_WhenPreviousAuthorizationHasBeenMade_Attestations_GenericWriteTrue_GenericReadTrue() - public - { - helperShouldSetTheNewAuthorized(Role.Attestation, true, true); - } - - function test_ShouldSetTheNewAuthorized_WhenPreviousAuthorizationHasBeenMade_Attestations_GenericWriteTrue_GenericReadFalse() - public - { - helperShouldSetTheNewAuthorized(Role.Attestation, true, false); - } - - function test_ShouldSetTheNewAuthorized_WhenPreviousAuthorizationHasBeenMade_Attestations_GenericWriteFalse_GenericReadTrue() - public - { - helperShouldSetTheNewAuthorized(Role.Attestation, false, true); - } - - function test_ShouldSetTheNewAuthorized_WhenPreviousAuthorizationHasBeenMade_Attestations_GenericWriteFalse_GenericReadFalse() - public - { - helperShouldSetTheNewAuthorized(Role.Attestation, false, false); - } - - function test_ShouldSetTheNewAuthorized_WhenPreviousAuthorizationHasBeenMade_Vote_GenericWriteTrue_GenericReadTrue() - public - { - helperShouldSetTheNewAuthorized(Role.Vote, true, true); - } - - function test_ShouldSetTheNewAuthorized_WhenPreviousAuthorizationHasBeenMade_Vote_GenericWriteTrue_GenericReadFalse() - public - { - helperShouldSetTheNewAuthorized(Role.Vote, true, false); - } - - function test_ShouldSetTheNewAuthorized_WhenPreviousAuthorizationHasBeenMade_Vote_GenericWriteFalse_GenericReadTrue() - public - { - helperShouldSetTheNewAuthorized(Role.Vote, false, true); - } - - function test_ShouldSetTheNewAuthorized_WhenPreviousAuthorizationHasBeenMade_Vote_GenericWriteFalse_GenericReadFalse() - public - { - helperShouldSetTheNewAuthorized(Role.Vote, false, false); - } - - function test_ShouldSetTheNewAuthorized_WhenPreviousAuthorizationHasBeenMade_Validator_GenericWriteTrue_GenericReadTrue() - public - { - helperShouldSetTheNewAuthorized(Role.Validator, true, true); - } - - function test_ShouldSetTheNewAuthorized_WhenPreviousAuthorizationHasBeenMade_Validator_GenericWriteTrue_GenericReadFalse() - public - { - helperShouldSetTheNewAuthorized(Role.Validator, true, false); - } - - function test_ShouldSetTheNewAuthorized_WhenPreviousAuthorizationHasBeenMade_Validator_GenericWriteFalse_GenericReadTrue() - public - { - helperShouldSetTheNewAuthorized(Role.Validator, false, true); - } - - function test_ShouldSetTheNewAuthorized_WhenPreviousAuthorizationHasBeenMade_Validator_GenericWriteFalse_GenericReadFalse() - public - { - helperShouldSetTheNewAuthorized(Role.Validator, false, false); - } - - function helperShouldReturnCorrectValues_WhenAccountHasNotAuthorized(Role role, bool genericRead) - public - { - assertEq(authorizedSignerToAccount(role, genericRead, account), account); - - vm.expectRevert("Must first register address with Account.createAccount"); - authorizedSignerToAccount(role, genericRead, otherAccount); - - assertEq(getAuthorizedFromAccount(role, genericRead, account), account); - } - - function test_ShouldReturnCorrectValues_WhenAccountHasNotAuthorized_Attestation_GenericReadTrue() - public - { - helperShouldReturnCorrectValues_WhenAccountHasNotAuthorized(Role.Attestation, true); - } - - function test_ShouldReturnCorrectValues_WhenAccountHasNotAuthorized_Attestation_GenericReadFalse() - public - { - helperShouldReturnCorrectValues_WhenAccountHasNotAuthorized(Role.Attestation, false); - } - - function test_ShouldReturnCorrectValues_WhenAccountHasNotAuthorized_Vote_GenericReadTrue() - public - { - helperShouldReturnCorrectValues_WhenAccountHasNotAuthorized(Role.Vote, true); - } - - function test_ShouldReturnCorrectValues_WhenAccountHasNotAuthorized_Vote_GenericReadFalse() - public - { - helperShouldReturnCorrectValues_WhenAccountHasNotAuthorized(Role.Vote, false); - } - - function test_ShouldReturnCorrectValues_WhenAccountHasNotAuthorized_Validator_GenericReadTrue() - public - { - helperShouldReturnCorrectValues_WhenAccountHasNotAuthorized(Role.Validator, true); - } - - function test_ShouldReturnCorrectValues_WhenAccountHasNotAuthorized_Validator_GenericReadFalse() - public - { - helperShouldReturnCorrectValues_WhenAccountHasNotAuthorized(Role.Validator, false); - } - - function helperShouldReturnCorrectValues_WhenAccountHasAuthorized( - Role role, - bool genericRead, - bool genericWrite - ) public { - assertEq(authorizedSignerToAccount(role, genericRead, account), account); - - authorize(role, genericWrite, account, signer, signerPK); - assertEq(authorizedSignerToAccount(role, genericRead, signer), account); - assertEq(getAuthorizedFromAccount(role, genericRead, account), signer); - } - - function test_ShouldReturnCorrectValues_WhenAccountHasAuthorized_Attestation_GenericReadTrue_GenericWriteTrue() - public - { - helperShouldReturnCorrectValues_WhenAccountHasAuthorized(Role.Attestation, true, true); - } - - function test_ShouldReturnCorrectValues_WhenAccountHasAuthorized_Attestation_GenericReadFalse_GenericWriteTrue() - public - { - helperShouldReturnCorrectValues_WhenAccountHasAuthorized(Role.Attestation, false, true); - } - - function test_ShouldReturnCorrectValues_WhenAccountHasAuthorized_Attestation_GenericReadTrue_GenericWriteFalse() - public - { - helperShouldReturnCorrectValues_WhenAccountHasAuthorized(Role.Attestation, true, false); - } - - function test_ShouldReturnCorrectValues_WhenAccountHasAuthorized_Attestation_GenericReadFalse_GenericWriteFalse() - public - { - helperShouldReturnCorrectValues_WhenAccountHasAuthorized(Role.Attestation, false, false); - } - - function test_ShouldReturnCorrectValues_WhenAccountHasAuthorized_Vote_GenericReadTrue_GenericWriteTrue() - public - { - helperShouldReturnCorrectValues_WhenAccountHasAuthorized(Role.Vote, true, true); - } - - function test_ShouldReturnCorrectValues_WhenAccountHasAuthorized_Vote_GenericReadFalse_GenericWriteTrue() - public - { - helperShouldReturnCorrectValues_WhenAccountHasAuthorized(Role.Vote, false, true); - } - - function test_ShouldReturnCorrectValues_WhenAccountHasAuthorized_Vote_GenericReadTrue_GenericWriteFalse() - public - { - helperShouldReturnCorrectValues_WhenAccountHasAuthorized(Role.Vote, true, false); - } - - function test_ShouldReturnCorrectValues_WhenAccountHasAuthorized_Vote_GenericReadFalse_GenericWriteFalse() - public - { - helperShouldReturnCorrectValues_WhenAccountHasAuthorized(Role.Vote, false, false); - } - - function test_ShouldReturnCorrectValues_WhenAccountHasAuthorized_Validator_GenericReadTrue_GenericWriteTrue() - public - { - helperShouldReturnCorrectValues_WhenAccountHasAuthorized(Role.Validator, true, true); - } - - function test_ShouldReturnCorrectValues_WhenAccountHasAuthorized_Validator_GenericReadFalse_GenericWriteTrue() - public - { - helperShouldReturnCorrectValues_WhenAccountHasAuthorized(Role.Validator, false, true); - } - - function test_ShouldReturnCorrectValues_WhenAccountHasAuthorized_Validator_GenericReadTrue_GenericWriteFalse() - public - { - helperShouldReturnCorrectValues_WhenAccountHasAuthorized(Role.Validator, true, false); - } - - function test_ShouldReturnCorrectValues_WhenAccountHasAuthorized_Validator_GenericReadFalse_GenericWriteFalse() - public - { - helperShouldReturnCorrectValues_WhenAccountHasAuthorized(Role.Validator, false, false); - } - - function helper_ShouldRemoveSigner(Role role, bool genericRead, bool genericWrite) public { - authorize(role, genericWrite, account, signer, signerPK); - assertEq(hasAuthorizedSigner(role, account, genericRead), true, "No authorized signer"); - assertEq( - getAuthorizedFromAccount(role, genericRead, account), - signer, - "authorized from account" - ); - - removeSigner(genericWrite, role, account); - - assertEq(hasAuthorizedSigner(role, account, genericRead), false, "Authorized signer"); - assertEq(getAuthorizedFromAccount(role, genericRead, account), account); - } - - function test_ShouldRemoveSigner_Attestations_GenericReadTrue_GenericWriteTrue() public { - helper_ShouldRemoveSigner(Role.Attestation, true, true); - } - - function test_ShouldRemoveSigner_Attestations_GenericReadFalse_GenericWriteTrue() public { - helper_ShouldRemoveSigner(Role.Attestation, false, true); - } - - function test_ShouldRemoveSigner_Attestations_GenericReadTrue_GenericWriteFalse() public { - helper_ShouldRemoveSigner(Role.Attestation, true, false); - } - - function test_ShouldRemoveSigner_Attestations_GenericReadFalse_GenericWriteFalse() public { - helper_ShouldRemoveSigner(Role.Attestation, false, true); - } - - function test_ShouldRemoveSigner_Vote_GenericReadTrue_GenericWriteTrue() public { - helper_ShouldRemoveSigner(Role.Vote, true, true); - } - - function test_ShouldRemoveSigner_Vote_GenericReadFalse_GenericWriteTrue() public { - helper_ShouldRemoveSigner(Role.Vote, false, true); - } - - function test_ShouldRemoveSigner_Vote_GenericReadTrue_GenericWriteFalse() public { - helper_ShouldRemoveSigner(Role.Vote, true, false); - } - - function test_ShouldRemoveSigner_Vote_GenericReadFalse_GenericWriteFalse() public { - helper_ShouldRemoveSigner(Role.Vote, false, true); - } - - function test_ShouldRemoveSigner_Validator_GenericReadTrue_GenericWriteTrue() public { - helper_ShouldRemoveSigner(Role.Validator, true, true); - } - - function test_ShouldRemoveSigner_Validator_GenericReadFalse_GenericWriteTrue() public { - helper_ShouldRemoveSigner(Role.Validator, false, true); - } - - function test_ShouldRemoveSigner_Validator_GenericReadTrue_GenericWriteFalse() public { - helper_ShouldRemoveSigner(Role.Validator, true, false); - } - - function test_ShouldRemoveSigner_Validator_GenericReadFalse_GenericWriteFalse() public { - helper_ShouldRemoveSigner(Role.Validator, false, true); - } -} diff --git a/packages/protocol/test-sol/common/AddressSortedLinkedListWithMedian.t.sol b/packages/protocol/test-sol/common/AddressSortedLinkedListWithMedian.t.sol deleted file mode 100644 index ecf9c4c39..000000000 --- a/packages/protocol/test-sol/common/AddressSortedLinkedListWithMedian.t.sol +++ /dev/null @@ -1,353 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.5.13; - -import "celo-foundry/Test.sol"; - -// Contract to test -import "@celo-contracts/common/test/AddressSortedLinkedListWithMedianTest.sol"; - -contract AddressSortedLinkedListWithMedianInsertTest is Test { - AddressSortedLinkedListWithMedianTest sortedList; - - address key = actor("key"); - uint256 numerator = 2; - - function setUp() public { - sortedList = new AddressSortedLinkedListWithMedianTest(); - } - - function test_ShouldAddASingleElementToTheList() public { - sortedList.insert(key, numerator, address(0), address(0)); - assertEq(sortedList.contains(key), true, "should contain the key"); - (address[] memory addresses, uint256[] memory numerators, ) = sortedList.getElements(); - assertEq(addresses.length, 1, "addresses should have a single element"); - assertEq(addresses[0], key, "should have the correct key"); - - assertEq(numerators.length, 1, "numerators should have a single element"); - assertEq(numerators[0], numerator, "should have the correct numerator"); - } - - function test_ShouldIncrementNumElements() public { - sortedList.insert(key, numerator, address(0), address(0)); - assertEq(sortedList.getNumElements(), 1, "should have a single element"); - } - - function test_ShouldUpdateTheHead() public { - sortedList.insert(key, numerator, address(0), address(0)); - assertEq(sortedList.head(), key, "should have the correct head"); - } - - function test_ShouldUpdateTheTail() public { - sortedList.insert(key, numerator, address(0), address(0)); - assertEq(sortedList.tail(), key, "should have the correct tail"); - } - - function test_ShouldUpdateTheMedian() public { - sortedList.insert(key, numerator, address(0), address(0)); - assertEq(sortedList.medianKey(), key, "should have the correct median"); - } - - function test_ShouldRevertIfKeyIsZero() public { - vm.expectRevert("invalid key"); - sortedList.insert(address(0), numerator, address(0), address(0)); - } - - function test_ShouldRevertIfLesserIsEqualToKey() public { - vm.expectRevert("invalid key"); - sortedList.insert(key, numerator, key, address(0)); - } - - function test_ShouldRevertIfGreaterIsEqualToKey() public { - vm.expectRevert("invalid key"); - sortedList.insert(key, numerator, address(0), key); - } - - function test_ShouldRevert_WhenInsertingElementAlreadyInTheList() public { - sortedList.insert(key, numerator, address(0), address(0)); - vm.expectRevert("invalid key"); - sortedList.insert(key, numerator, address(0), address(0)); - } -} - -contract AddressSortedLinkedListWithMedianUpdateTest is Test { - AddressSortedLinkedListWithMedianTest sortedList; - - address key = actor("key"); - address key2 = actor("key2"); - uint256 numerator = 2; - uint256 newNumerator = 3; - - function setUp() public { - sortedList = new AddressSortedLinkedListWithMedianTest(); - sortedList.insert(key, numerator, address(0), address(0)); - } - - function test_ShouldUpdateValueForAnExistingElement() public { - sortedList.update(key, newNumerator, address(0), address(0)); - (address[] memory addresses, uint256[] memory numerators, ) = sortedList.getElements(); - assertEq(addresses.length, 1, "addresses should have a single element"); - assertEq(addresses[0], key, "should have the correct key"); - - assertEq(numerators.length, 1, "numerators should have a single element"); - assertEq(numerators[0], newNumerator, "should have the correct numerator"); - } - - function test_ShouldRevertIfTheKEyIsNotInTheList() public { - vm.expectRevert("key not in list"); - sortedList.update(key2, newNumerator, address(0), address(0)); - } - - function test_ShouldRevertIfLesserIsEqualToKey() public { - vm.expectRevert("invalid key"); - sortedList.update(key, newNumerator, key, address(0)); - } - - function test_ShouldRevertIfGreaterIsEqualToKey() public { - vm.expectRevert("invalid key"); - sortedList.update(key, newNumerator, address(0), key); - } -} - -contract AddressSortedLinkedListWithMedianRemoveTest is Test { - AddressSortedLinkedListWithMedianTest sortedList; - - address key = actor("key"); - address key2 = actor("key2"); - uint256 numerator = 2; - - function setUp() public { - sortedList = new AddressSortedLinkedListWithMedianTest(); - sortedList.insert(key, numerator, address(0), address(0)); - } - - function test_ShouldRemoveTheELementFromTheList() public { - sortedList.remove(key); - assertEq(sortedList.contains(key), false, "should not contain the key"); - } - - function test_ShouldDecrementNumElements() public { - sortedList.remove(key); - assertEq(sortedList.getNumElements(), 0, "should have no elements"); - } - - function test_ShouldUpdateTheHead() public { - sortedList.remove(key); - assertEq(sortedList.head(), address(0), "should have the correct head"); - } - - function test_ShouldUpdateTheTail() public { - sortedList.remove(key); - assertEq(sortedList.tail(), address(0), "should have the correct tail"); - } - - function test_ShouldUpdateTheMedian() public { - sortedList.remove(key); - assertEq(sortedList.medianKey(), address(0), "should have the correct median"); - } - - function test_ShouldRevertIfTheKeyIsNotInTheList() public { - vm.expectRevert("key not in list"); - sortedList.remove(key2); - } -} - -contract AddressSortedLinkedListWithMedianWhenThereAreMultipleActionsTest is Test { - AddressSortedLinkedListWithMedianTest sortedList; - - uint256 nonce = 0; - - enum SortedListActionType { Update, Remove, Insert } - - struct SortedElement { - address key; - uint256 numerator; - } - - struct SortedListAction { - SortedListActionType actionType; - SortedElement element; - } - - function setUp() public { - sortedList = new AddressSortedLinkedListWithMedianTest(); - } - - function getLesserAndGreater(uint256 numerator) - internal - view - returns (address lesser, address greater) - { - // Fetch all elements from the list - (address[] memory keys, uint256[] memory numerators, ) = sortedList.getElements(); - uint256 length = keys.length; - - lesser = address(0); // Initialize with the default values - greater = address(0); - - for (uint256 i = 0; i < length; i++) { - // Find the first key with a numerator greater than the given one - if (numerators[i] > numerator) { - greater = keys[i]; - if (i > 0) { - lesser = keys[i - 1]; - } - break; - } - } - - // If no greater key is found, the last key in the list is considered `lesser` - if (greater == address(0) && length > 0) { - lesser = keys[length - 1]; - } - } - - function random(uint256 maxNumber) public returns (uint256) { - nonce += 1; - return - uint256(keccak256(abi.encodePacked(nonce, msg.sender, blockhash(block.number - 1)))) % - maxNumber; - } - - function getLesserAndGreaterIncorrect() internal returns (address lesser, address greater) { - (address[] memory keys, , ) = sortedList.getElements(); - - uint256 random1 = random(100); - if (random1 < 50) { - return (address(0), address(0)); - } else { - uint256 random2 = random(keys.length); - uint256 random3 = random(keys.length); - return (keys[random2], keys[random3]); - } - } - - function assertSortedFractionListInvariants() internal view { - // Fetch all elements from the list - (address[] memory keys, uint256[] memory numerators, SortedLinkedListWithMedian.MedianRelation[] memory relations) = sortedList - .getElements(); - uint256 numElements = sortedList.getNumElements(); // Assuming getNumElements() returns the total number of elements - address medianKey = sortedList.medianKey(); // Assuming medianKey() returns the key of the median element - - // Assert the number of elements is correct - require(keys.length == numElements, "Incorrect number of elements"); - - // Assert keys are sorted in descending order of numerators - for (uint256 i = 1; i < keys.length; i++) { - require(numerators[i - 1] >= numerators[i], "Elements not sorted"); - } - - // Assert median key is correct - uint256 medianIndex = (keys.length - 1) / 2; - require(keys.length == 0 || keys[medianIndex] == medianKey, "Incorrect median element"); - - // Assert relations are correct according to median - for (uint256 i = 0; i < relations.length; i++) { - if (i < medianIndex) { - require( - relations[i] == SortedLinkedListWithMedian.MedianRelation.Greater, - "Incorrect relation for lesser element" - ); - } else if (i == medianIndex) { - require( - relations[i] == SortedLinkedListWithMedian.MedianRelation.Equal, - "Incorrect relation for median element" - ); - } else { - require( - relations[i] == SortedLinkedListWithMedian.MedianRelation.Lesser, - "Incorrect relation for greater element" - ); - } - } - } - - function test_MultipleInsertsUpdatesRemovals() public { - address[100] memory keys; - uint256[100] memory numerators; - - // Initialize keys and numerators - for (uint256 i = 0; i < 100; i++) { - keys[i] = address(uint160(i + 1)); - numerators[i] = i * 100; // Example numerator values - } - - // Simulating the action sequence - for (uint256 i = 0; i < 100; i++) { - address key = keys[i]; - uint256 numerator = numerators[i]; - - // Randomly decide on action: Insert, Update, or Remove - uint256 actionType = i % 3; // This is a simplification of random selection - - if (actionType == uint256(SortedListActionType.Insert)) { - (address greater, address lesser) = getLesserAndGreater(numerator); - sortedList.insert(key, numerator, greater, lesser); - assertTrue(sortedList.contains(key)); - } else if (actionType == uint256(SortedListActionType.Update)) { - if (sortedList.contains(key)) { - (address greater, address lesser) = getLesserAndGreater(numerator); - sortedList.update(key, numerator + 1, greater, lesser); - } - } else if (actionType == uint256(SortedListActionType.Remove)) { - if (sortedList.contains(key)) { - sortedList.remove(key); - assertFalse(sortedList.contains(key)); - } - } - } - - assertSortedFractionListInvariants(); - } - - function test_MultipleInsertsUpdatesRemovalsIncorrectGreaterAndLesser() public { - address[100] memory keys; - uint256[100] memory numerators; - - // Initialize keys and numerators - for (uint256 i = 0; i < 100; i++) { - keys[i] = address(uint160(i + 1)); - numerators[i] = i * 100; // Example numerator values - } - - // Simulating the action sequence - for (uint256 i = 0; i < 100; i++) { - address key = keys[i]; - uint256 numerator = numerators[i]; - - // Randomly decide on action: Insert, Update, or Remove - uint256 actionType = i % 3; // This is a simplification of random selection - - if (actionType == uint256(SortedListActionType.Insert)) { - (address greater, address lesser) = getLesserAndGreaterIncorrect(); - (bool success, ) = address(sortedList).call( - abi.encodeWithSelector(sortedList.insert.selector, key, numerator, greater, lesser) - ); - if (success) { - assertTrue(sortedList.contains(key)); - } - // Handle failure case if needed - } else if (actionType == uint256(SortedListActionType.Update)) { - if (sortedList.contains(key)) { - (address greater, address lesser) = getLesserAndGreaterIncorrect(); - (bool success, ) = address(sortedList).call( - abi.encodeWithSelector(sortedList.update.selector, key, numerator + 1, greater, lesser) - ); - if (success) { - assertTrue(sortedList.contains(key)); - } - } - } else if (actionType == uint256(SortedListActionType.Remove)) { - if (sortedList.contains(key)) { - (bool success, ) = address(sortedList).call( - abi.encodeWithSelector(sortedList.remove.selector, key) - ); - if (success) { - assertFalse(sortedList.contains(key)); - } - } - } - } - - assertSortedFractionListInvariants(); - } -} diff --git a/packages/protocol/test-sol/common/ExtractFunctionSignature.t.sol b/packages/protocol/test-sol/common/ExtractFunctionSignature.t.sol deleted file mode 100644 index dfcdbbfc6..000000000 --- a/packages/protocol/test-sol/common/ExtractFunctionSignature.t.sol +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.5.13; - -import "celo-foundry/Test.sol"; - -// Contract to test -import "@celo-contracts/common/ExtractFunctionSignature.sol"; - -contract ExtractFunctionSignatureWrapper { - function extractFunctionSignature(bytes memory input) public pure returns (bytes4) { - return ExtractFunctionSignature.extractFunctionSignature(input); - } -} - -contract TestTransactions { - mapping(uint256 => uint256) public values; - - function getValue(uint256 key) external view returns (uint256) { - return values[key]; - } - - function setValue(uint256 key, uint256 value, bool shouldSucceed) external { - require(shouldSucceed); - values[key] = value; - } -} - -contract ExtractFunctionSignatureTest is Test { - ExtractFunctionSignatureWrapper extractFunctionSignature; - TestTransactions testTransactions; - - function setUp() public { - extractFunctionSignature = new ExtractFunctionSignatureWrapper(); - testTransactions = new TestTransactions(); - } - - function test_ExtractFunctionSignature() public { - // Arrange - bytes memory data = abi.encodeWithSignature("setValue(uint256,uint256,bool)", 1, 1, true); - bytes4 expectedSignature = bytes4(keccak256("setValue(uint256,uint256,bool)")); - - // Act - bytes4 result = extractFunctionSignature.extractFunctionSignature(data); - - // Assert - assertEq(result, expectedSignature); - } -} diff --git a/packages/protocol/test-sol/common/Fixidity.t.sol b/packages/protocol/test-sol/common/Fixidity.t.sol deleted file mode 100644 index e72d6d038..000000000 --- a/packages/protocol/test-sol/common/Fixidity.t.sol +++ /dev/null @@ -1,229 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.5.13; - -import "celo-foundry/Test.sol"; - -// Contract to test -import "@celo-contracts/common/test/FixidityWrapper.sol"; - -contract FixidityTest is Test { - uint256 private constant FIXED1_UINT = 1000000000000000000000000; - uint256 private constant MAX_NEW_FIXED = 115792089237316195423570985008687907853269984665640564; - uint256 private constant MAX_NEW_FIXED_ADD = 57896044618658097711785492504343953926634992332820282019728792003956564819967; - uint256 private constant MAX_UINT256 = 115792089237316195423570985008687907853269984665640564039457584007913129639935; - uint256 private constant MAX_FIXED_MUL = 340282366920938463463374607431768211455999999999999; - uint256 private constant MAX_FIXED_DIV = 115792089237316195423570985008687907853269984665640564; - uint256 private constant MUL_PRECISION = 1000000000000; - - FixidityWrapper fixidity; - - function setUp() public { - fixidity = new FixidityWrapper(); - } - - function test_zero_fixed() public { - assertEq(fixidity.newFixed(0), 0); - } - - function test_one_fixed() public { - assertEq(fixidity.newFixed(1), FIXED1_UINT); - } - - function test_create_maxNewFixed() public { - assertEq( - fixidity.newFixed(MAX_NEW_FIXED), - 115792089237316195423570985008687907853269984665640564000000000000000000000000 - ); - } - - function test_new_fixed_plus_one() public { - vm.expectRevert("can't create fixidity number larger than maxNewFixed()"); - fixidity.newFixed(MAX_NEW_FIXED + 1); - } - - function test_fraction_one() public { - assertEq(fixidity.newFixedFraction(1, 1), FIXED1_UINT); - } - - function test_fraction_zero() public { - assertEq(fixidity.newFixedFraction(0, 1), 0); - } - - function test_fraction_one_fixed() public { - assertEq(fixidity.newFixedFraction(1, FIXED1_UINT), 1); - } - - function test_fraction_zero_denominator() public { - vm.expectRevert("can't divide by 0"); - fixidity.newFixedFraction(1, 0); - } - - function test_fraction_add_interger() public { - uint256 a = fixidity.newFixed(2); - uint256 b = fixidity.newFixed(3); - - assertEq(fixidity.add(a, b), fixidity.newFixed(5)); - } - - function test_fraction_add_fraction() public { - uint256 a = fixidity.newFixedFraction(242, 100); - uint256 b = fixidity.newFixedFraction(363, 100); - - assertEq(fixidity.add(a, b), fixidity.newFixedFraction(605, 100)); - } - - function add_two_maxFixedAdd_numbers() public { - fixidity.add(MAX_NEW_FIXED_ADD, MAX_NEW_FIXED_ADD); - - assertEq(fixidity.add(MAX_NEW_FIXED_ADD, MAX_NEW_FIXED_ADD), MAX_NEW_FIXED - 1); - } - - function test_no_maxFixed_add() public { - uint256 fixedAdd1 = MAX_NEW_FIXED_ADD + 1; - - vm.expectRevert("add overflow detected"); - fixidity.add(fixedAdd1, fixedAdd1); - } - - function test_no_add_maxUint256() public { - vm.expectRevert("add overflow detected"); - fixidity.add(MAX_UINT256, 1); - } - - function test_substract_integers() public { - uint256 a = fixidity.newFixedFraction(100, 10); - uint256 b = fixidity.newFixedFraction(60, 10); - uint256 expected = fixidity.newFixedFraction(40, 10); - - uint256 result = fixidity.subtract(a, b); - assertEq(result, expected); - } - - function test_substract_fractions() public { - uint256 a = fixidity.newFixedFraction(234, 10); - uint256 b = fixidity.newFixedFraction(232, 10); - uint256 expected = fixidity.newFixedFraction(2, 10); - - uint256 result = fixidity.subtract(a, b); - assertEq(result, expected); - } - - function test_substract_fail_small_large_number() public { - uint256 a = fixidity.newFixedFraction(60, 10); - uint256 b = fixidity.newFixedFraction(100, 10); - - vm.expectRevert("substraction underflow detected"); - fixidity.subtract(a, b); - } - - function test_multiply_integers() public { - uint256 a = fixidity.newFixedFraction(70, 10); - uint256 b = fixidity.newFixedFraction(60, 10); - uint256 expected = fixidity.newFixedFraction(420, 10); - - uint256 result = fixidity.multiply(a, b); - assertEq(result, expected); - } - - function test_multiply_fraction() public { - uint256 a = fixidity.newFixedFraction(13, 10); - uint256 b = fixidity.newFixedFraction(42, 10); - uint256 expected = fixidity.newFixedFraction(546, 100); - - uint256 result = fixidity.multiply(a, b); - assertEq(result, expected); - } - - function test_multiply_by_zero() public { - assertEq(fixidity.multiply(FIXED1_UINT, 0), 0); - } - - function test_multiply_maxFixedMul() public { - uint256 result = fixidity.multiply(MAX_FIXED_MUL, MAX_FIXED_MUL); - uint256 expected = 115792089237316195423570985008687907853269984665639883474723742130122666467811; - assertEq(result, expected); - } - - function test_multiply_retain_presition() public { - uint256 a = fixidity.divide(FIXED1_UINT, MUL_PRECISION); - uint256 b = fixidity.multiply(FIXED1_UINT, MUL_PRECISION); - - uint256 result = fixidity.multiply(a, b); - - assertEq(result, FIXED1_UINT); - } - - function test_multiply_fails_larger_than_maxFixedMul() public { - uint256 a = MAX_FIXED_MUL + 1; - - vm.expectRevert("add overflow detected"); - - fixidity.multiply(a, a); - } - - function test_reciprocal_fixed1() public { - assertEq(fixidity.reciprocal(FIXED1_UINT), FIXED1_UINT); - } - - function test_divide_intergers() public { - uint256 a = fixidity.newFixedFraction(840, 10); - uint256 b = fixidity.newFixedFraction(20, 10); - uint256 expected = fixidity.newFixedFraction(420, 10); - - uint256 result = fixidity.divide(a, b); - assertEq(result, expected); - } - - function test_divide_fractions() public { - uint256 a = fixidity.newFixedFraction(18, 10); - uint256 b = fixidity.newFixedFraction(15, 10); - uint256 expected = fixidity.newFixedFraction(12, 10); - - uint256 result = fixidity.divide(a, b); - assertEq(result, expected); - } - - function test_divide_maxFixedDividend_1() public { - assertEq(fixidity.divide(MAX_FIXED_DIV, 1), MAX_FIXED_DIV * FIXED1_UINT); - } - - function test_divide_fail_more_than_max_div() public { - vm.expectRevert("overflow at divide"); - fixidity.divide(MAX_FIXED_DIV + 1, 1); - } - - function test_divide_fail_divide_zero() public { - vm.expectRevert("can't divide by 0"); - fixidity.divide(MAX_FIXED_DIV, 0); - } - - function test_comparison_first_number_greather() public { - uint256 a = 2; - uint256 b = 1; - - assertTrue(fixidity.gt(a, b)); - assertTrue(fixidity.gte(a, b)); - assertFalse(fixidity.lt(a, b)); - assertFalse(fixidity.lte(a, b)); - } - - function test_comparison_numbers_equal() public { - uint256 a = 2; - uint256 b = 2; - - assertFalse(fixidity.gt(a, b)); - assertTrue(fixidity.gte(a, b)); - assertFalse(fixidity.lt(a, b)); - assertTrue(fixidity.lte(a, b)); - } - - function test_comparison_first_number_smaller() public { - uint256 a = 1; - uint256 b = 2; - - assertFalse(fixidity.gt(a, b)); - assertFalse(fixidity.gte(a, b)); - assertTrue(fixidity.lt(a, b)); - assertTrue(fixidity.lte(a, b)); - } -} diff --git a/packages/protocol/test-sol/common/GoldToken.t.sol b/packages/protocol/test-sol/common/GoldToken.t.sol deleted file mode 100644 index 32ab7b0a9..000000000 --- a/packages/protocol/test-sol/common/GoldToken.t.sol +++ /dev/null @@ -1,200 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.5.13; - -import "celo-foundry/Test.sol"; -import "@celo-contracts/common/GoldToken.sol"; -import "@celo-contracts/common/test/MockGoldToken.sol"; - -contract GoldTokenTest is Test { - GoldToken goldToken; - uint256 ONE_GOLDTOKEN = 1000000000000000000; - address receiver; - address sender; - - event Transfer(address indexed from, address indexed to, uint256 value); - event TransferComment(string comment); - - function setUp() public { - goldToken = new GoldToken(true); - receiver = actor("receiver"); - receiver = actor("sender"); - vm.deal(receiver, ONE_GOLDTOKEN); - vm.deal(sender, ONE_GOLDTOKEN); - } -} - -contract BasicGoldTokenTest is GoldTokenTest { - function setUp() public { - super.setUp(); - } - - function test_name() public { - assertEq(goldToken.name(), "Celo native asset"); - } - - function test_symbol() public { - assertEq(goldToken.symbol(), "CELO"); - } - - function test_decimals() public { - assertEq(uint256(goldToken.decimals()), 18); - } - - function test_balanceOf() public { - assertEq(goldToken.balanceOf(receiver), receiver.balance); - } - - function test_approve() public { - vm.prank(sender); - goldToken.approve(receiver, ONE_GOLDTOKEN); - assertEq(goldToken.allowance(sender, receiver), ONE_GOLDTOKEN); - } - - function test_increaseAllowance() public { - vm.prank(sender); - goldToken.increaseAllowance(receiver, ONE_GOLDTOKEN); - vm.prank(sender); - goldToken.increaseAllowance(receiver, ONE_GOLDTOKEN); - assertEq(goldToken.allowance(sender, receiver), ONE_GOLDTOKEN * 2); - } - - function test_decreaseAllowance() public { - vm.prank(sender); - goldToken.approve(receiver, ONE_GOLDTOKEN * 2); - vm.prank(sender); - goldToken.decreaseAllowance(receiver, ONE_GOLDTOKEN); - assertEq(goldToken.allowance(sender, receiver), ONE_GOLDTOKEN); - } - - function test_allowance() public { - vm.prank(sender); - goldToken.approve(receiver, ONE_GOLDTOKEN); - assertEq(goldToken.allowance(sender, receiver), ONE_GOLDTOKEN); - } -} - -contract GoldTokenTransfer is GoldTokenTest { - function setUp() public { - super.setUp(); - } - - function testTransfer_ShouldTransferBalanceFromOneUserToAnother() public { - uint256 startBalanceFrom = goldToken.balanceOf(sender); - uint256 startBalanceTo = goldToken.balanceOf(receiver); - vm.prank(sender); - goldToken.transfer(receiver, ONE_GOLDTOKEN); - assertEq(sender.balance, startBalanceFrom - ONE_GOLDTOKEN); - assertEq(receiver.balance, startBalanceTo + ONE_GOLDTOKEN); - } - - function testTransfer_ShouldTransferBalanceWithAComment() public { - string memory comment = "tacos at lunch"; - uint256 startBalanceFrom = goldToken.balanceOf(sender); - uint256 startBalanceTo = goldToken.balanceOf(receiver); - vm.prank(sender); - vm.expectEmit(true, true, true, true); - emit Transfer(sender, receiver, ONE_GOLDTOKEN); - vm.expectEmit(true, true, true, true); - emit TransferComment(comment); - goldToken.transferWithComment(receiver, ONE_GOLDTOKEN, comment); - assertEq(sender.balance, startBalanceFrom - ONE_GOLDTOKEN); - assertEq(receiver.balance, startBalanceTo + ONE_GOLDTOKEN); - } - - function testTransfer_ShouldNotAllowToTransferToNullAddress() public { - vm.prank(sender); - vm.expectRevert(); - goldToken.transfer(address(0), ONE_GOLDTOKEN); - } -} - -contract GoldTokenTransferFrom is GoldTokenTest { - function setUp() public { - super.setUp(); - vm.prank(sender); - goldToken.approve(receiver, ONE_GOLDTOKEN); - } - - function test_ShouldTransferBalanceFromOneUserToAnother() public { - uint256 startBalanceFrom = goldToken.balanceOf(sender); - uint256 startBalanceTo = goldToken.balanceOf(receiver); - vm.prank(receiver); - goldToken.transferFrom(sender, receiver, ONE_GOLDTOKEN); - assertEq(sender.balance, startBalanceFrom - ONE_GOLDTOKEN); - assertEq(receiver.balance, startBalanceTo + ONE_GOLDTOKEN); - } - - function testTransfer_ShouldNotAllowToTransferToNullAddress() public { - vm.prank(receiver); - vm.expectRevert(); - goldToken.transferFrom(sender, address(0), ONE_GOLDTOKEN); - } - - function testTransfer_ShouldNotAllowTransferMoreThanSenderHas() public { - uint256 value = sender.balance + ONE_GOLDTOKEN * 4; - - vm.prank(receiver); - vm.expectRevert(); - goldToken.transferFrom(sender, receiver, value); - } - - function testTransfer_ShouldNotAllowTransferringMoreThanTheSpenderIsAllowed() public { - vm.prank(receiver); - vm.expectRevert(); - goldToken.transferFrom(sender, receiver, ONE_GOLDTOKEN + 1); - } -} - -contract BurnGoldToken is GoldTokenTest { - uint256 startBurn; - address burnAddress = address(0x000000000000000000000000000000000000dEaD); - - function setUp() public { - super.setUp(); - startBurn = goldToken.getBurnedAmount(); - } - - function test_burn_address_starts_with_zero_balance() public { - assertEq(goldToken.balanceOf(burnAddress), 0); - } - - function test_burn_starts_as_start_burn_amount() public { - assertEq(goldToken.getBurnedAmount(), startBurn); - } - - function test_burn_amount_eq_the_balance_of_the_burn_address() public { - assertEq(goldToken.getBurnedAmount(), goldToken.balanceOf(burnAddress)); - } - - function test_returns_right_burn_amount() public { - goldToken.burn(ONE_GOLDTOKEN); - assertEq(goldToken.getBurnedAmount(), ONE_GOLDTOKEN + startBurn); - } -} - -contract MockGoldTokenTest is Test { - MockGoldToken mockGoldToken; - uint256 ONE_GOLDTOKEN = 1000000000000000000; - address burnAddress = address(0x000000000000000000000000000000000000dEaD); - - function setUp() public { - mockGoldToken = new MockGoldToken(); - mockGoldToken.setTotalSupply(ONE_GOLDTOKEN * 1000); - } -} - -contract MockGoldTokenCirculatingSupply is MockGoldTokenTest { - function setUp() public { - super.setUp(); - } - - function test_ShouldMatchCirculationSupply_WhenNoBurn() public { - assertEq(mockGoldToken.circulatingSupply(), mockGoldToken.totalSupply()); - } - - function test_ShouldDecreaseCirculatingSupply_WhenThereWasBurn() public { - mockGoldToken.setBalanceOf(burnAddress, ONE_GOLDTOKEN); - assertEq(mockGoldToken.circulatingSupply(), ONE_GOLDTOKEN * 999); - assertEq(mockGoldToken.circulatingSupply(), mockGoldToken.totalSupply() - ONE_GOLDTOKEN); - } -} diff --git a/packages/protocol/test-sol/common/Heap.t.sol b/packages/protocol/test-sol/common/Heap.t.sol deleted file mode 100644 index 134d96235..000000000 --- a/packages/protocol/test-sol/common/Heap.t.sol +++ /dev/null @@ -1,110 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.5.13; - -import "celo-foundry/Test.sol"; -import "../../contracts/common/libraries/Heap.sol"; -import "forge-std/console.sol"; - -contract HeapTest { - using FixidityLib for FixidityLib.Fraction; - - function swapKeys(uint256[] memory keys, uint256 i, uint256 j) internal pure { - uint256 tmp = keys[i]; - keys[i] = keys[j]; - keys[j] = tmp; - } - - function sort(uint256[] memory intValues) public pure returns (uint256[] memory) { - uint256 length = intValues.length; - FixidityLib.Fraction[] memory values = new FixidityLib.Fraction[](length); - uint256[] memory keys = new uint256[](length); - for (uint256 i = 0; i < length; i++) { - keys[i] = i; - values[i] = FixidityLib.wrap(intValues[i]); - } - // heapify - for (int256 start = int256(length / 2); start >= 0; start--) { - Heap.siftDown(keys, values, uint256(start), length); - } - for (uint256 end = length; end > 0; end--) { - swapKeys(keys, end - 1, 0); - Heap.siftDown(keys, values, 0, end - 1); - } - uint256[] memory result = new uint256[](length); - for (uint256 i = 0; i < length; i++) { - result[i] = values[keys[i]].unwrap(); - } - return result; - } -} - -contract HeapTestTestFoundry is Test { - HeapTest heapTest; - - mapping(uint256 => bool) public helperMapping; - - function setUp() public { - heapTest = new HeapTest(); - } - - function generatePRN(uint256 min, uint256 max, uint256 salt) public view returns (uint256) { - return - (uint256(keccak256(abi.encodePacked(block.timestamp, block.difficulty, msg.sender, salt))) % - (max - min + 1)) + - min; - } - - function generateRandomArray(uint256 min, uint256 max, uint256 length, bool repeatingAllowed) - public - returns (uint256[] memory) - { - require(max > min, "Max must be greater than min"); - require(length <= (max - min + 1) || repeatingAllowed, "Not enough unique numbers available"); - - uint256[] memory array = new uint256[](length); - - for (uint256 i = 0; i < length; ) { - uint256 randomNumber = generatePRN(min, max, i); - - if (repeatingAllowed) { - array[i] = randomNumber; - i++; - } else { - if (!helperMapping[randomNumber]) { - array[i] = randomNumber; - i++; - } else { - helperMapping[randomNumber] = true; - } - } - } - - if (!repeatingAllowed) { - for (uint256 i = 0; i < length; i++) { - helperMapping[array[i]] = false; - } - } - - return array; - } - - function test_SortWithRandomListsNonRepeatingItems() public { - for (uint256 i = 0; i < 1000; i++) { - uint256[] memory array = generateRandomArray(0, 10, 10, false); - uint256[] memory sortedArray = heapTest.sort(array); - for (uint256 j = 0; j < 9; j++) { - assertEq(sortedArray[j] <= sortedArray[j + 1], true, "Array is not sorted"); - } - } - } - - function test_SortWithRandomListsRepeatingItems() public { - for (uint256 i = 0; i < 1000; i++) { - uint256[] memory array = generateRandomArray(0, 10, 10, true); - uint256[] memory sortedArray = heapTest.sort(array); - for (uint256 j = 0; j < 9; j++) { - assertEq(sortedArray[j] <= sortedArray[j + 1], true, "Array is not sorted"); - } - } - } -} diff --git a/packages/protocol/test-sol/common/LinkedList.t.sol b/packages/protocol/test-sol/common/LinkedList.t.sol deleted file mode 100644 index fd96169e5..000000000 --- a/packages/protocol/test-sol/common/LinkedList.t.sol +++ /dev/null @@ -1,139 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.5.13; - -import "celo-foundry/Test.sol"; - -// Contract to test -import "@celo-contracts/common/test/LinkedListWrapper.sol"; - -contract LinkedListInsert is Test { - LinkedListWrapper linkedList; - bytes32 private constant NULL_KEY = bytes32(uint256(0x00)); - bytes32 private constant FIRST_KEY = bytes32(uint256(0x01)); - bytes32 private constant SECOND_KEY = bytes32(uint256(0x02)); - bytes32 private constant THIRD_KEY = bytes32(uint256(0x03)); - bytes32 private constant ADDED_KEY = bytes32(uint256(0x04)); - function setUp() public { - linkedList = new LinkedListWrapper(); - } - - function setUpListWithManyElements() private { - linkedList.insert(FIRST_KEY, NULL_KEY, NULL_KEY); - linkedList.insert(SECOND_KEY, NULL_KEY, FIRST_KEY); - linkedList.insert(THIRD_KEY, NULL_KEY, SECOND_KEY); - } - - function testRevertIf_PreviousIsEqualToKeyWhenEmpty() public { - vm.expectRevert("Key cannot be the same as previousKey or nextKey"); - linkedList.insert(ADDED_KEY, ADDED_KEY, NULL_KEY); - } - function testRevertIf_NextIsEqualToKeyWhenEmpty() public { - vm.expectRevert("Key cannot be the same as previousKey or nextKey"); - linkedList.insert(ADDED_KEY, NULL_KEY, ADDED_KEY); - } - - function testRevertIf_NextIsEqualToKeyWhenInsertingToSingleton() public { - linkedList.insert(FIRST_KEY, NULL_KEY, NULL_KEY); - vm.expectRevert("Key cannot be the same as previousKey or nextKey"); - linkedList.insert(ADDED_KEY, FIRST_KEY, ADDED_KEY); - } - - function testRevertIf_PreviousIsEqualToKeyWhenInsertingToSingleton() public { - linkedList.insert(FIRST_KEY, NULL_KEY, NULL_KEY); - vm.expectRevert("Key cannot be the same as previousKey or nextKey"); - linkedList.insert(ADDED_KEY, ADDED_KEY, FIRST_KEY); - } - - function testRevertIf_NextIsEqualToKey_beginning_ManyElements() public { - setUpListWithManyElements(); - vm.expectRevert("Key cannot be the same as previousKey or nextKey"); - linkedList.insert(ADDED_KEY, FIRST_KEY, ADDED_KEY); - } - - function testRevertIf_PreviousIsEqualToKey_beginning_ManyElements() public { - setUpListWithManyElements(); - vm.expectRevert("Key cannot be the same as previousKey or nextKey"); - linkedList.insert(ADDED_KEY, ADDED_KEY, FIRST_KEY); - } - - function testRevertIf_NextIsEqualToKey_end_ManyElements() public { - setUpListWithManyElements(); - vm.expectRevert("Key cannot be the same as previousKey or nextKey"); - linkedList.insert(ADDED_KEY, THIRD_KEY, ADDED_KEY); - } - - function testRevertIf_PreviousIsEqualToKey_end_ManyElements() public { - setUpListWithManyElements(); - vm.expectRevert("Key cannot be the same as previousKey or nextKey"); - linkedList.insert(ADDED_KEY, ADDED_KEY, THIRD_KEY); - } - - function testRevertIf_NextIsEqualToKey_middle_ManyElements() public { - setUpListWithManyElements(); - vm.expectRevert("Key cannot be the same as previousKey or nextKey"); - linkedList.insert(ADDED_KEY, SECOND_KEY, ADDED_KEY); - } - - function testRevertIf_PreviousIsEqualToKey_middle_ManyElements() public { - setUpListWithManyElements(); - vm.expectRevert("Key cannot be the same as previousKey or nextKey"); - linkedList.insert(ADDED_KEY, ADDED_KEY, SECOND_KEY); - } - - function testRevertIf_NextAndPreviousEqualToKey_ManyElements() public { - setUpListWithManyElements(); - vm.expectRevert("Key cannot be the same as previousKey or nextKey"); - linkedList.insert(ADDED_KEY, ADDED_KEY, ADDED_KEY); - } -} - -contract LinkedListRemove is Test { - LinkedListWrapper linkedList; - - bytes32 private constant NULL_KEY = bytes32(uint256(0x00)); - bytes32 private constant FIRST_KEY = bytes32(uint256(0x01)); - bytes32 private constant SECOND_KEY = bytes32(uint256(0x02)); - bytes32 private constant THIRD_KEY = bytes32(uint256(0x03)); - bytes32 private constant ADDED_KEY = bytes32(uint256(0x04)); - - function setUp() public { - linkedList = new LinkedListWrapper(); - } - - function setUpListWithManyElements() private { - linkedList.insert(FIRST_KEY, NULL_KEY, NULL_KEY); - linkedList.insert(SECOND_KEY, FIRST_KEY, NULL_KEY); - linkedList.insert(THIRD_KEY, SECOND_KEY, NULL_KEY); - } - - function testRevertIf_RemovingFromAnEmptyList() public { - vm.expectRevert("key not in list"); - linkedList.remove(FIRST_KEY); - } - - function test_CanRemoveFirstElement() public { - setUpListWithManyElements(); - linkedList.remove(FIRST_KEY); - assertFalse(linkedList.contains(FIRST_KEY)); - } - - function test_AfterRemoveSecondElementIsHead() public { - setUpListWithManyElements(); - linkedList.remove(FIRST_KEY); - bytes32 tail = linkedList.tail(); - assertEq(tail, SECOND_KEY); - } - - function test_ReduceNumberOfElementsByOne() public { - setUpListWithManyElements(); - linkedList.remove(FIRST_KEY); - assertEq(linkedList.getNumElements(), 2); - } - - function testRevertIf_removingAlreadyRemovedElement() public { - setUpListWithManyElements(); - linkedList.remove(FIRST_KEY); - vm.expectRevert("key not in list"); - linkedList.remove(FIRST_KEY); - } -} diff --git a/packages/protocol/test-sol/common/Multisig.t.sol b/packages/protocol/test-sol/common/Multisig.t.sol deleted file mode 100644 index 9eff14cd4..000000000 --- a/packages/protocol/test-sol/common/Multisig.t.sol +++ /dev/null @@ -1,426 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.5.13; - -import "celo-foundry/Test.sol"; -import "@celo-contracts/common/MultiSig.sol"; - -contract MultiSigTest is Test { - function() external payable {} - - MultiSig public multiSig; - address owner0; - address owner1; - address newOwner; - address nonOwner; - address sender; - uint256 requiredSignatures = 2; - uint256 internalRequiredSignatures = 2; - address[] public owners; - bytes addOwnerTxData; - - event Confirmation(address indexed sender, uint256 indexed transactionId); - event Revocation(address indexed sender, uint256 indexed transactionId); - event Submission(uint256 indexed transactionId); - event Execution(uint256 indexed transactionId, bytes returnData); - event Deposit(address indexed sender, uint256 value); - event OwnerAddition(address indexed owner); - event OwnerRemoval(address indexed owner); - event RequirementChange(uint256 required); - event InternalRequirementChange(uint256 internalRequired); - - function setUp() public { - multiSig = new MultiSig(true); - owner0 = actor("owner0"); - owner1 = actor("owner1"); - sender = actor("sender"); - newOwner = actor("newOwner"); - nonOwner = actor("nonOwner"); - vm.deal(sender, 10 ether); - owners = [owner0, owner1]; - - addOwnerTxData = abi.encodeWithSignature("addOwner(address)", newOwner); - - multiSig.initialize(owners, requiredSignatures, internalRequiredSignatures); - } -} - -contract MultiSigInitialize is MultiSigTest { - function setUp() public { - super.setUp(); - } - - function test_shouldHaveSetTheOwners() public { - assertEq(multiSig.getOwners(), owners); - } - - function test_shouldHaveSetTheNumberOfRequiredSignaturesForExternalTransactions() public { - assertEq(uint256(multiSig.required()), 2); - } - - function test_shouldHaveSetTheNumberOfRequiredSignaturesForInternalTransactions() public { - assertEq(uint256(multiSig.internalRequired()), 2); - } - - function test_revertsWhenCalledTwice() public { - vm.expectRevert("contract already initialized"); - multiSig.initialize(owners, requiredSignatures, internalRequiredSignatures); - } -} - -contract MultiSigFallbackFunction is MultiSigTest { - uint256 amount = 100; - - function setUp() public { - super.setUp(); - } - - function uncheckedSendViaCall(address payable _to, uint256 _amount) public payable { - _to.call.value(_amount)(""); - } - - function test_emitsDepositEventWithCorrectParameters_whenReceivingCelo() public payable { - vm.prank(sender); - vm.expectEmit(true, false, false, false); - emit Deposit(sender, amount); - uncheckedSendViaCall(address(multiSig), amount); - } - - // TODO: Implement after pragma ^0.8 - function SKIP_test_doesNotEmitEvent_whenReceivingZeroValue() public { - vm.prank(sender); - vm.recordLogs(); - uncheckedSendViaCall(address(multiSig), 0); - // Vm.Log[] memory entries = vm.getRecordedLogs(); - // assertEq(entries.length, 0); - } -} - -contract MultiSigSubmitTransaction is MultiSigTest { - uint256 txId = 0; - - function setUp() public { - super.setUp(); - } - - function test_shouldAllowAnOwnerToSubmitATransaction() public { - vm.prank(owner0); - vm.expectEmit(true, true, true, true); - emit Confirmation(owner0, txId); - multiSig.submitTransaction(address(multiSig), 0, addOwnerTxData); - - (address dest, uint256 val, bytes memory data, bool exec) = multiSig.transactions(txId); - - assertEq(dest, address(multiSig)); - assertEq(val, 0); - assertEq(data, addOwnerTxData); - assertEq(exec, false); - assertEq(multiSig.confirmations(txId, owner0), true); - assertEq(multiSig.transactionCount(), 1); - } - - function test_shouldNotAllowAnOwnerToSubmitATransactionToANullAddress() public { - vm.expectRevert("address was null"); - multiSig.submitTransaction(address(0), 0, addOwnerTxData); - } - - function test_shouldNotAllowANonOwnerToSubmitATransaction() public { - vm.expectRevert("owner does not exist"); - multiSig.submitTransaction(address(multiSig), 0, addOwnerTxData); - } -} - -contract MultiSigConfirmTransaction is MultiSigTest { - uint256 txId = 0; - - function setUp() public { - super.setUp(); - vm.prank(owner0); - multiSig.submitTransaction(address(multiSig), 0, addOwnerTxData); - } - - function test_shouldAllowAnOwnerToConfirmTransaction() public { - vm.prank(owner1); - multiSig.confirmTransaction(txId); - - assertEq(multiSig.confirmations(txId, owner1), true); - - (, , , bool exec) = multiSig.transactions(txId); - assertEq(exec, true); - } - - function test_shouldNotAllowAnOwnerToConfirmATransactionTwice() public { - vm.prank(owner0); - vm.expectRevert("transaction was already confirmed for owner"); - multiSig.confirmTransaction(txId); - } - - function test_shouldNotAllowANonOwnerToConfirmATransaction() public { - vm.prank(nonOwner); - vm.expectRevert("owner does not exist"); - multiSig.confirmTransaction(txId); - } -} - -contract MultiSigRevokeConfirmation is MultiSigTest { - uint256 txId = 0; - - function setUp() public { - super.setUp(); - vm.prank(owner0); - multiSig.submitTransaction(address(multiSig), 0, addOwnerTxData); - } - - function test_shouldAllowAnOwnerToRevokeConfirmation() public { - vm.prank(owner0); - multiSig.revokeConfirmation(txId); - assertEq(multiSig.confirmations(txId, owner0), false); - } - - function test_shouldNotAllowANonOwnerToRevokeConfirmation() public { - vm.prank(nonOwner); - vm.expectRevert("owner does not exist"); - multiSig.revokeConfirmation(txId); - } - - function test_shouldNotAllowAnOwnerToRevokeBeforeConfirming() public { - vm.prank(owner1); - vm.expectRevert("transaction was not confirmed for owner"); - multiSig.revokeConfirmation(txId); - } -} - -contract MultiSigAddOwner is MultiSigTest { - uint256 txId = 0; - address[] public updatedOwners; - - function setUp() public { - super.setUp(); - updatedOwners = [owner0, owner1, newOwner]; - } - - function test_shouldAllowNewOwnerToBeAddedViaMultiSig() public { - vm.prank(owner0); - multiSig.submitTransaction(address(multiSig), 0, addOwnerTxData); - vm.prank(owner1); - multiSig.confirmTransaction(txId); - assertEq(multiSig.isOwner(newOwner), true); - - assertEq(multiSig.getOwners(), updatedOwners); - } - - function test_shouldNotAllowAnExternalAccountToAddAnOwner() public { - vm.prank(nonOwner); - vm.expectRevert("msg.sender was not multisig wallet"); - multiSig.addOwner(newOwner); - } - - function test_shouldNotAllowAddingTheNullAddress() public { - bytes memory txData_null = abi.encodeWithSignature("addOwner(address)", address(0)); - vm.prank(owner0); - multiSig.submitTransaction(address(multiSig), 0, txData_null); - - vm.prank(owner1); - vm.expectRevert("Transaction execution failed."); - multiSig.confirmTransaction(txId); - } -} - -contract MultiSigRemoveOwner is MultiSigTest { - uint256 txId = 0; - address[] public updatedOwners; - - function setUp() public { - super.setUp(); - updatedOwners = [owner0]; - } - - function test_shouldAllowOwnerToBeRemovedViaMultiSig() public { - bytes memory txData_remove = abi.encodeWithSignature("removeOwner(address)", owner1); - vm.prank(owner0); - multiSig.submitTransaction(address(multiSig), 0, txData_remove); - - vm.prank(owner1); - multiSig.confirmTransaction(txId); - - assertEq(multiSig.isOwner(owner1), false); - assertEq(multiSig.required(), 1); - assertEq(multiSig.internalRequired(), 1); - assertEq(multiSig.getOwners(), updatedOwners); - } - - function test_shouldNotAllowAnExternalAccountToRemoveAnOwner() public { - vm.prank(nonOwner); - vm.expectRevert("msg.sender was not multisig wallet"); - multiSig.removeOwner(newOwner); - } -} - -contract MultiSigReplaceOwner is MultiSigTest { - uint256 txId = 0; - address[] public updatedOwners; - - function setUp() public { - super.setUp(); - updatedOwners = [owner0, newOwner]; - } - - function test_shouldAllowAnExistingOwnerToBeReplacedViaMultiSig() public { - bytes memory txData_replace = abi.encodeWithSignature( - "replaceOwner(address,address)", - owner1, - newOwner - ); - vm.prank(owner0); - multiSig.submitTransaction(address(multiSig), 0, txData_replace); - - vm.prank(owner1); - multiSig.confirmTransaction(txId); - - assertEq(multiSig.isOwner(owner1), false); - assertEq(multiSig.isOwner(newOwner), true); - assertEq(multiSig.getOwners(), updatedOwners); - } - - function test_shouldNotAllowAnExternalAccountToReplaceAnOwner() public { - vm.prank(nonOwner); - vm.expectRevert("msg.sender was not multisig wallet"); - multiSig.replaceOwner(owner1, newOwner); - } - - function test_shouldNotAllowAnOwnerToBeReplacedByNullAddress() public { - bytes memory txData_replace = abi.encodeWithSignature( - "replaceOwner(address,address)", - owner1, - address(0) - ); - vm.prank(owner0); - multiSig.submitTransaction(address(multiSig), 0, txData_replace); - - vm.prank(owner1); - vm.expectRevert("Transaction execution failed."); - multiSig.confirmTransaction(txId); - } -} - -contract MultiSigChangeRequirements is MultiSigTest { - uint256 txId = 0; - - function setUp() public { - super.setUp(); - } - - function test_shouldAllowTheRequirementToBeChangedViaMultiSig() public { - bytes memory txData_change_req = abi.encodeWithSignature("changeRequirement(uint256)", 1); - - vm.prank(owner0); - multiSig.submitTransaction(address(multiSig), 0, txData_change_req); - - vm.prank(owner1); - multiSig.confirmTransaction(txId); - assertEq(multiSig.required(), 1); - } - - function test_shouldNotAllowAnExternalAccountToChangeTheRequirement() public { - vm.prank(nonOwner); - vm.expectRevert("msg.sender was not multisig wallet"); - multiSig.changeRequirement(3); - } -} - -contract MultiSigChangeInternalRequirements is MultiSigTest { - uint256 txId = 0; - - function setUp() public { - super.setUp(); - } - - function test_shouldAllowTheInternalRequirementToBeChangedViaMultiSig() public { - bytes memory txData_change_req = abi.encodeWithSignature( - "changeInternalRequirement(uint256)", - 1 - ); - - vm.prank(owner0); - multiSig.submitTransaction(address(multiSig), 0, txData_change_req); - - vm.prank(owner1); - multiSig.confirmTransaction(txId); - assertEq(multiSig.internalRequired(), 1); - } - - function test_shouldNotAllowAnExternalAccountToChangeTheInternalRequirement() public { - vm.prank(nonOwner); - vm.expectRevert("msg.sender was not multisig wallet"); - multiSig.changeInternalRequirement(3); - } -} - -contract MultiSigGetConfirmationCount is MultiSigTest { - uint256 txId = 0; - - function setUp() public { - super.setUp(); - vm.prank(owner0); - multiSig.submitTransaction(address(multiSig), 0, addOwnerTxData); - } - - function test_shouldReturnTheConfirmationCount() public { - assertEq(multiSig.getConfirmationCount(txId), 1); - } -} - -contract MultiSigGetTransactionCount is MultiSigTest { - uint256 txId = 0; - - function setUp() public { - super.setUp(); - vm.prank(owner0); - multiSig.submitTransaction(address(multiSig), 0, addOwnerTxData); - } - - function test_shouldReturnTheTransactionCount() public { - assertEq(multiSig.getTransactionCount(true, true), 1); - } -} - -contract MultiSigGetOwners is MultiSigTest { - function setUp() public { - super.setUp(); - } - - function test_shouldReturnTheOwners() public { - assertEq(multiSig.getOwners(), owners); - } -} - -contract MultiSigGetConfirmations is MultiSigTest { - uint256 txId = 0; - - function setUp() public { - super.setUp(); - vm.prank(owner0); - multiSig.submitTransaction(address(multiSig), 0, addOwnerTxData); - } - - function test_shouldReturnTheConfirmations() public { - address[] memory expectedConfirmations = new address[](1); - expectedConfirmations[0] = owner0; - assertEq(multiSig.getConfirmations(txId), expectedConfirmations); - } -} - -contract MultiSigGetTransactionIds is MultiSigTest { - uint256 txId = 0; - - function setUp() public { - super.setUp(); - vm.prank(owner0); - multiSig.submitTransaction(address(multiSig), 0, addOwnerTxData); - } - - function test_shouldReturnTheTransactionIds() public { - uint256[] memory expectedTransactionIds = new uint256[](1); - expectedTransactionIds[0] = txId; - assertEq(multiSig.getTransactionIds(0, 1, true, true), expectedTransactionIds); - } -} diff --git a/packages/protocol/test-sol/common/Registry.t.sol b/packages/protocol/test-sol/common/Registry.t.sol deleted file mode 100644 index bcb55a18c..000000000 --- a/packages/protocol/test-sol/common/Registry.t.sol +++ /dev/null @@ -1,93 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.5.13; - -import "celo-foundry/Test.sol"; - -// Contract to test -import "@celo-contracts/common/Registry.sol"; - -contract RegistryTest is Test { - event RegistryUpdated(string identifier, bytes32 indexed identifierHash, address indexed addr); - - address constant SOME_ADDRESS = address(0x06012c8cf97BEaD5deAe237070F9587f8E7A266d); - string constant SOME_ID = "cryptokitties"; - // hash of SOME_ID - // hash is harcoded to avoid test and implementation chaing in at the same time - bytes32 constant ID_HASH = 0x05445421d7b4d4c2e571c5a4ccf9317ec68601449f752c75ddbcc61a16061004; - - Registry registry; - address owner; - - function setUp() public { - owner = address(this); - vm.prank(owner); - registry = new Registry(true); - registry.initialize(); - } - - function test_initialize_has_right_owner() public { - assertEq(registry.owner(), owner); - } - - function test_initialize_cant_called_again() public { - vm.expectRevert("contract already initialized"); - registry.initialize(); - } - - function test_setAddressFor_set_address() public { - vm.prank(owner); - registry.setAddressFor(SOME_ID, SOME_ADDRESS); - assertEq(registry.registry(ID_HASH), SOME_ADDRESS); - } - - function test_setAddressFor_reverts_other_user() public { - vm.expectRevert("Ownable: caller is not the owner"); - vm.prank(msg.sender); - registry.setAddressFor(SOME_ID, SOME_ADDRESS); - } - - function test_setAddressFor_emits() public { - vm.expectEmit(true, true, false, true); - emit RegistryUpdated(SOME_ID, ID_HASH, SOME_ADDRESS); - - registry.setAddressFor(SOME_ID, SOME_ADDRESS); - } - - function test_getAddressForOrDie_gets_address() public { - registry.setAddressFor(SOME_ID, SOME_ADDRESS); - assertEq(registry.getAddressForOrDie(ID_HASH), SOME_ADDRESS); - } - - function test_getAddressForOrDie_reverts_address_not_set() public { - vm.expectRevert("identifier has no registry entry"); - registry.getAddressForOrDie(ID_HASH); - } - - function test_getAddressFor_gets_address() public { - registry.setAddressFor(SOME_ID, SOME_ADDRESS); - assertEq(registry.getAddressFor(ID_HASH), SOME_ADDRESS); - } - - function test_getAddressFor_doesnt_revert() public { - assertEq(registry.getAddressFor(ID_HASH), address(0)); - } - - function test_getAddressForStringOrDie_gets_address() public { - registry.setAddressFor(SOME_ID, SOME_ADDRESS); - assertEq(registry.getAddressForStringOrDie(SOME_ID), SOME_ADDRESS); - } - - function test_getAddressForStringOrDie_reverts() public { - vm.expectRevert("identifier has no registry entry"); - registry.getAddressForStringOrDie(SOME_ID); - } - - function test_getAddressForString_gets_addres() public { - registry.setAddressFor(SOME_ID, SOME_ADDRESS); - assertEq(registry.getAddressForString(SOME_ID), SOME_ADDRESS); - } - - function test_getAddressForString_shoudlnt_revert() public view { - registry.getAddressForString(SOME_ID); - } -} diff --git a/packages/protocol/test-sol/constants.sol b/packages/protocol/test-sol/constants.sol deleted file mode 100644 index 3db2fae47..000000000 --- a/packages/protocol/test-sol/constants.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -// This contract is only required for Solidity 0.5 -contract Constants { - uint256 public constant FIXED1 = 1e24; - uint256 constant YEAR = 365 * 24 * 60 * 60; - - // contract names - string constant ElectionContract = "Election"; - string constant SortedOraclesContract = "SortedOracles"; - string constant StableTokenContract = "StableToken"; - string constant GoldTokenContract = "GoldToken"; - string constant FreezerContract = "Freezer"; -} diff --git a/packages/protocol/test-sol/governance/network/EpochRewards.t.sol b/packages/protocol/test-sol/governance/network/EpochRewards.t.sol deleted file mode 100644 index 1d42d9804..000000000 --- a/packages/protocol/test-sol/governance/network/EpochRewards.t.sol +++ /dev/null @@ -1,930 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.5.13; - -import "celo-foundry/Test.sol"; -import "@celo-contracts/common/Registry.sol"; -import "@celo-contracts/common/Freezer.sol"; - -import { MockElection } from "@celo-contracts/governance/test/MockElection.sol"; -import { EpochRewardsTest } from "@celo-contracts/governance/test/EpochRewardsTest.sol"; -import { Reserve } from "@lib/mento-core/contracts/Reserve.sol"; - -import { MockSortedOracles } from "@celo-contracts/stability/test/MockSortedOracles.sol"; -import { MockStableToken } from "@celo-contracts/stability/test/MockStableToken.sol"; -import { MockGoldToken } from "@celo-contracts/common/test/MockGoldToken.sol"; - -import { Constants } from "@test-sol/constants.sol"; -import { Utils } from "@test-sol/utils.sol"; - -contract EpochRewardsFoundryTest is Test, Constants, Utils { - event TargetVotingGoldFractionSet(uint256 fraction); - event CommunityRewardFractionSet(uint256 fraction); - event TargetValidatorEpochPaymentSet(uint256 payment); - event RewardsMultiplierParametersSet( - uint256 max, - uint256 underspendAdjustmentFactor, - uint256 overspendAdjustmentFactor - ); - event TargetVotingYieldParametersSet(uint256 max, uint256 adjustmentFactor); - event TargetVotingYieldSet(uint256 target); - - uint256 constant targetVotingYieldParamsInitial = 0.00016e24; // 0.00016 - uint256 constant targetVotingYieldParamsMax = 0.0005e24; // 0.0005 - uint256 constant targetVotingYieldParamsAdjustmentFactor = 1127990000000000000; // 0.00000112799 - - uint256 constant rewardsMultiplierMax = 2 * FIXED1; // 2 - uint256 constant rewardsMultiplierAdjustmentsUnderspend = 0.5e24; // 0.5 - uint256 constant rewardsMultiplierAdjustmentsOverspend = 5e24; // 5 - - uint256 constant targetVotingGoldFraction = (2 * FIXED1) / uint256(3); - uint256 constant targetValidatorEpochPayment = 1e13; - uint256 constant communityRewardFraction = FIXED1 / 4; - uint256 constant carbonOffsettingFraction = FIXED1 / 200; - - uint256 constant exchangeRate = 7; - uint256 constant sortedOraclesDenominator = FIXED1; - - uint256 constant SUPPLY_CAP = 1e9 ether; - bytes32[] initialAssetAllocationSymbols; - uint256[] initialAssetAllocationWeights; - - // Mocked contracts - EpochRewardsTest epochRewards; - MockElection mockElection; - MockSortedOracles mockSortedOracles; - MockStableToken mockStableToken; - MockGoldToken mockGoldToken; - Reserve reserve; - Freezer freezer; - - Registry registry; - - address caller = address(this); - - function getExpectedTargetTotalSupply(uint256 timeDelta) internal pure returns (uint256) { - uint256 genesisSupply = 600000000 ether; - uint256 linearRewards = 200000000 ether; - return uint256(genesisSupply + (timeDelta * linearRewards) / (YEAR * 15)); - } - - function setUp() public { - // Mocked contracts - epochRewards = new EpochRewardsTest(); - mockElection = new MockElection(); - mockSortedOracles = new MockSortedOracles(); - mockStableToken = new MockStableToken(); - mockGoldToken = new MockGoldToken(); - - freezer = new Freezer(true); - registry = new Registry(true); - - registry.setAddressFor(ElectionContract, address(mockElection)); - registry.setAddressFor(SortedOraclesContract, address(mockSortedOracles)); - registry.setAddressFor(StableTokenContract, address(mockStableToken)); - registry.setAddressFor(GoldTokenContract, address(mockGoldToken)); - registry.setAddressFor(FreezerContract, address(freezer)); - - mockSortedOracles.setMedianRate( - address(mockStableToken), - sortedOraclesDenominator * exchangeRate - ); - - epochRewards.initialize( - address(registry), - targetVotingYieldParamsInitial, - targetVotingYieldParamsMax, - targetVotingYieldParamsAdjustmentFactor, - rewardsMultiplierMax, - rewardsMultiplierAdjustmentsUnderspend, - rewardsMultiplierAdjustmentsOverspend, - targetVotingGoldFraction, - targetValidatorEpochPayment, - communityRewardFraction, - address(0), - carbonOffsettingFraction - ); - - } - -} - -contract EpochRewardsFoundryTest_Initialize is EpochRewardsFoundryTest { - function test_ShouldHaveSetOwner() public { - assertEq(epochRewards.owner(), caller); - } - - function test_ShouldHaveSetTargetValidatorEpochPayment() public { - assertEq(epochRewards.targetValidatorEpochPayment(), targetValidatorEpochPayment); - } - - function test_ShouldHaveSetTargetRewardMultiplierParameter() public { - uint256 target; - uint256 max; - uint256 adjustmentFactor; - (target, max, adjustmentFactor) = epochRewards.getTargetVotingYieldParameters(); - - assertEq(target, targetVotingYieldParamsInitial); - assertEq(max, targetVotingYieldParamsMax); - assertEq(adjustmentFactor, targetVotingYieldParamsAdjustmentFactor); - } - - function test_ShouldHaveSetRewardsMultiplier() public { - uint256 max; - uint256 underspend; - uint256 overspend; - (max, underspend, overspend) = epochRewards.getRewardsMultiplierParameters(); - - assertEq(max, rewardsMultiplierMax); - assertEq(underspend, rewardsMultiplierAdjustmentsUnderspend); - assertEq(overspend, rewardsMultiplierAdjustmentsOverspend); - } - - function test_shouldNotBeCallableAgain() public { - vm.expectRevert("contract already initialized"); - epochRewards.initialize( - address(registry), - targetVotingYieldParamsInitial, - targetVotingYieldParamsMax, - targetVotingYieldParamsAdjustmentFactor, - rewardsMultiplierMax, - rewardsMultiplierAdjustmentsUnderspend, - rewardsMultiplierAdjustmentsOverspend, - targetVotingGoldFraction, - targetValidatorEpochPayment, - communityRewardFraction, - address(0), - carbonOffsettingFraction - ); - } - -} - -contract EpochRewardsFoundryTest_SetTargetVotingGoldFraction is EpochRewardsFoundryTest { - uint256 newFraction; - - function setUp() public { - super.setUp(); - newFraction = targetVotingGoldFraction + 1; - } - - function test_ShouldSetTargetVotingGoldFraction_WhenFractionIsDifferent_WhenCalledByOwner() - public - { - epochRewards.setTargetVotingGoldFraction(newFraction); - assertEq(epochRewards.getTargetVotingGoldFraction(), newFraction); - } - - function test_ShouldEmitTargetVotingGoldFractionSet_WhenFractionIsDifferent_WhenCalledByOwner() - public - { - vm.expectEmit(true, true, true, true); - emit TargetVotingGoldFractionSet(newFraction); - epochRewards.setTargetVotingGoldFraction(newFraction); - } - - function test_ShouldRevert_WhenFractionIsDifferent_WhenCalledByNonOwner() public { - vm.prank(msg.sender); - vm.expectRevert("Ownable: caller is not the owner"); - epochRewards.setTargetVotingGoldFraction(newFraction); - } - - function test_ShouldRevert_WhenFractionIsSame_WhenCalledByOwner() public { - vm.expectRevert("Target voting gold fraction unchanged"); - epochRewards.setTargetVotingGoldFraction(targetVotingGoldFraction); - } - -} - -contract EpochRewardsFoundryTest_SetCommunityRewardFraction is EpochRewardsFoundryTest { - uint256 newFraction = communityRewardFraction + 1; - - function test_ShouldSetTargetVotingGoldFraction_WhenFractionIsDifferent_WhenCalledByOwner() - public - { - epochRewards.setCommunityRewardFraction(newFraction); - assertEq(epochRewards.getCommunityRewardFraction(), newFraction); - } - - function test_ShouldEmitCommunityRewardFractionSet_WhenFractionIsDifferent_WhenCalledByOwner() - public - { - vm.expectEmit(true, true, true, true); - emit CommunityRewardFractionSet(newFraction); - epochRewards.setCommunityRewardFraction(newFraction); - } - - function test_ShouldRevert_WhenFractionIsDifferent_WhenCalledByNonOwner() public { - vm.prank(msg.sender); - vm.expectRevert("Ownable: caller is not the owner"); - epochRewards.setCommunityRewardFraction(newFraction); - } - - function test_ShouldRevert_WhenFractionIsDifferent_WhenCalledByOwner() public { - vm.expectRevert( - "Value must be different from existing community reward fraction and less than 1" - ); - epochRewards.setCommunityRewardFraction(communityRewardFraction); - } - - function test_ShouldBeLessThan1() public { - vm.expectRevert( - "Value must be different from existing community reward fraction and less than 1" - ); - epochRewards.setCommunityRewardFraction(1000000 ether); - } -} - -contract EpochRewardsFoundryTest_SetTargetValidatorEpochPayment is EpochRewardsFoundryTest { - uint256 newPayment = targetValidatorEpochPayment + 1; - - function test_ShouldSetTargetVotingGoldFraction_WhenPaymentIsDifferent_WhenCalledByOwner() - public - { - epochRewards.setTargetValidatorEpochPayment(newPayment); - assertEq(epochRewards.targetValidatorEpochPayment(), newPayment); - } - - function test_ShouldEmitTargetValidatorEpochPaymentSet_WhenPaymentIsDifferent_WhenCalledByOwner() - public - { - vm.expectEmit(true, true, true, true); - emit TargetValidatorEpochPaymentSet(newPayment); - epochRewards.setTargetValidatorEpochPayment(newPayment); - } - - function test_ShouldRevert_WhenPaymentIsDifferent_WhenCalledByNonOwner() public { - vm.prank(msg.sender); - vm.expectRevert("Ownable: caller is not the owner"); - epochRewards.setTargetValidatorEpochPayment(newPayment); - } - - function test_ShouldRevert_WhenFractionIsDifferent_WhenCalledByOwner() public { - vm.expectRevert("Target validator epoch payment unchanged"); - epochRewards.setTargetValidatorEpochPayment(targetValidatorEpochPayment); - } -} - -contract EpochRewardsFoundryTest_SetRewardsMultiplierParameters is EpochRewardsFoundryTest { - uint256 newRewardsMultiplierAdjustmentsUnderspend = rewardsMultiplierAdjustmentsUnderspend + 1; - - function test_ShouldSetNewRewardsMultiplierAdjustmentsOverspend_WhenCalledByOwner() public { - epochRewards.setRewardsMultiplierParameters( - rewardsMultiplierMax, - newRewardsMultiplierAdjustmentsUnderspend, - rewardsMultiplierAdjustmentsOverspend - ); - - (uint256 max, uint256 underspend, uint256 overspend) = epochRewards - .getRewardsMultiplierParameters(); - - assertEq(max, rewardsMultiplierMax); - assertEq(underspend, newRewardsMultiplierAdjustmentsUnderspend); - assertEq(overspend, rewardsMultiplierAdjustmentsOverspend); - } - - function test_ShouldEmitRewardsMultiplierParametersSet_WhenCalledByOwner() public { - vm.expectEmit(true, true, true, true); - emit RewardsMultiplierParametersSet( - rewardsMultiplierMax, - newRewardsMultiplierAdjustmentsUnderspend, - rewardsMultiplierAdjustmentsOverspend - ); - epochRewards.setRewardsMultiplierParameters( - rewardsMultiplierMax, - newRewardsMultiplierAdjustmentsUnderspend, - rewardsMultiplierAdjustmentsOverspend - ); - } - - function test_ShouldRevert_WhenCalledByOwner() public { - vm.prank(msg.sender); - vm.expectRevert("Ownable: caller is not the owner"); - epochRewards.setRewardsMultiplierParameters( - rewardsMultiplierMax, - newRewardsMultiplierAdjustmentsUnderspend, - rewardsMultiplierAdjustmentsOverspend - ); - } - - function test_ShouldRevert_WhenCalledByNonOwner_WhenParameterAreTheSame() public { - vm.expectRevert("Bad rewards multiplier parameters"); - epochRewards.setRewardsMultiplierParameters( - rewardsMultiplierMax, - rewardsMultiplierAdjustmentsUnderspend, - rewardsMultiplierAdjustmentsOverspend - ); - } -} - -contract EpochRewardsFoundryTest_SetTargetVotingYieldParameters is EpochRewardsFoundryTest { - uint256 newTargetVotingYieldParamsMax = targetVotingYieldParamsMax + 1; - uint256 newTargetVotingYieldParamsAdjustmentFactor = targetVotingYieldParamsAdjustmentFactor + 1; - - function test_ShouldSetNewTargetVotingYieldParameters_WhenCalledByOwner() public { - epochRewards.setTargetVotingYieldParameters( - newTargetVotingYieldParamsMax, - newTargetVotingYieldParamsAdjustmentFactor - ); - - (, uint256 max, uint256 factor) = epochRewards.getTargetVotingYieldParameters(); - - assertEq(max, newTargetVotingYieldParamsMax); - assertEq(factor, newTargetVotingYieldParamsAdjustmentFactor); - } - - function test_ShouldEmitTargetVotingYieldParametersSet_WhenCalledByOwner() public { - vm.expectEmit(true, true, true, true); - emit TargetVotingYieldParametersSet( - newTargetVotingYieldParamsMax, - newTargetVotingYieldParamsAdjustmentFactor - ); - epochRewards.setTargetVotingYieldParameters( - newTargetVotingYieldParamsMax, - newTargetVotingYieldParamsAdjustmentFactor - ); - } - - function test_ShouldRevert_WhenCalledByOwner_WhenParameterAreTheSame() public { - vm.expectRevert("Bad target voting yield parameters"); - epochRewards.setTargetVotingYieldParameters( - targetVotingYieldParamsMax, - targetVotingYieldParamsAdjustmentFactor - ); - } - - function test_ShouldRevert_WhenCalledByNonOwner() public { - vm.prank(msg.sender); - vm.expectRevert("Ownable: caller is not the owner"); - epochRewards.setTargetVotingYieldParameters( - newTargetVotingYieldParamsMax, - newTargetVotingYieldParamsAdjustmentFactor - ); - } -} - -contract EpochRewardsFoundryTest_SetTargetVotingYield is EpochRewardsFoundryTest { - uint256 constant newTargetVotingYieldParamsInitial = targetVotingYieldParamsInitial + 1; - - function test_ShouldSetNewTargetVotingYieldParamsInitial_WhenCalledByOwner() public { - epochRewards.setTargetVotingYield(newTargetVotingYieldParamsInitial); - - (uint256 target, , ) = epochRewards.getTargetVotingYieldParameters(); - assertEq(target, newTargetVotingYieldParamsInitial); - } - - function test_ShouldEmitTargetVotingYieldSet_WhenCalledByOwner() public { - vm.expectEmit(true, true, true, true); - emit TargetVotingYieldSet(newTargetVotingYieldParamsInitial); - epochRewards.setTargetVotingYield(newTargetVotingYieldParamsInitial); - } - - function test_ShouldRevert_WhenCalledByNonOwner() public { - vm.prank(msg.sender); - vm.expectRevert("Ownable: caller is not the owner"); - epochRewards.setTargetVotingYield(newTargetVotingYieldParamsInitial); - } -} - -contract EpochRewardsFoundryTest_getTargetGoldTotalSupply is EpochRewardsFoundryTest { - function test_ShouldReturn1B_WhenLessThan15YearsSinceGenesis() public { - uint256 timeDelta = YEAR * 10; - timeTravel(timeDelta); - assertEq(epochRewards.getTargetGoldTotalSupply(), getExpectedTargetTotalSupply(timeDelta)); - } - -} - -contract EpochRewardsFoundryTest_getTargetVoterRewards is EpochRewardsFoundryTest { - function test_ShouldReturnAPercentageOfActiveVotes_WhenThereAreActiveVotes() public { - uint256 activeVotes = 1000000; - mockElection.setActiveVotes(activeVotes); - - uint256 expected = uint256((activeVotes * targetVotingYieldParamsInitial) / FIXED1); - assertEq(epochRewards.getTargetVoterRewards(), expected); - } - -} - -contract EpochRewardsFoundryTest_getTargetTotalEpochPaymentsInGold is EpochRewardsFoundryTest { - function test_ShouldgetTargetTotalEpochPaymentsInGold_WhenExchangeRateIsSet() public { - uint256 numberValidators = 100; - epochRewards.setNumberValidatorsInCurrentSet(numberValidators); - - uint256 expected = uint256((targetValidatorEpochPayment * numberValidators) / exchangeRate); - assertEq(epochRewards.getTargetTotalEpochPaymentsInGold(), expected); - } - -} - -contract EpochRewardsFoundryTest_getRewardsMultiplier is EpochRewardsFoundryTest { - uint256 constant timeDelta = YEAR * 10; - uint256 expectedTargetTotalSupply; - uint256 expectedTargetRemainingSupply; - uint256 targetEpochReward; - - function setUp() public { - super.setUp(); - expectedTargetTotalSupply = getExpectedTargetTotalSupply(timeDelta); - expectedTargetRemainingSupply = SUPPLY_CAP - expectedTargetTotalSupply; - targetEpochReward = - epochRewards.getTargetVoterRewards() + - epochRewards.getTargetTotalEpochPaymentsInGold(); - timeTravel(timeDelta); - } - - function test_ShouldReturnOne_WhenTheTargetSupplyIsEqualToTheActualSupplyAfterRewards() public { - mockGoldToken.setTotalSupply(expectedTargetTotalSupply - targetEpochReward); - assertEq(epochRewards.getRewardsMultiplier(), FIXED1); - } - - function test_ShouldReturnOnePlus10pTimesTheUnderspendAdjustment_WhenTheActualRemainingSupplyIs10pMoreThanTheTargetRemainingSupplyAfterRewards() - public - { - uint256 actualRemainingSupply = uint256((expectedTargetRemainingSupply * 11) / 10); - uint256 totalSupply = SUPPLY_CAP - actualRemainingSupply - targetEpochReward; - mockGoldToken.setTotalSupply(totalSupply); - - uint256 actual = epochRewards.getRewardsMultiplier(); - uint256 expected = uint256((FIXED1 + (rewardsMultiplierAdjustmentsUnderspend / 10))); - assertApproxEqRel(actual, expected, 1e6); - } - - function test_ShouldReturnOneMinus10pTimesTheUnderspendAdjustment_WhenTheActualRemainingSupplyIs10PLessThanTheTargetRemainingSupplyAfterRewards() - public - { - uint256 actualRemainingSupply = uint256((expectedTargetRemainingSupply * 9) / 10); - uint256 totalSupply = SUPPLY_CAP - actualRemainingSupply - targetEpochReward; - mockGoldToken.setTotalSupply(totalSupply); - - uint256 actual = epochRewards.getRewardsMultiplier(); - uint256 expected = uint256((FIXED1 - (rewardsMultiplierAdjustmentsOverspend / 10))); - assertApproxEqRel(actual, expected, 1e6); - - } - -} - -contract EpochRewardsFoundryTest_updateTargetVotingYield is EpochRewardsFoundryTest { - uint256 constant totalSupply = 6000000 ether; - uint256 constant reserveBalance = 1000000 ether; - uint256 constant floatingSupply = totalSupply - reserveBalance; - - function setUp() public { - super.setUp(); - reserve = new Reserve(true); - - registry.setAddressFor("Reserve", address(reserve)); - - initialAssetAllocationWeights = new uint256[](1); - initialAssetAllocationWeights[0] = FIXED1; - - initialAssetAllocationSymbols = new bytes32[](1); - initialAssetAllocationSymbols[0] = bytes32("cGLD"); - - reserve.initialize( - address(registry), - 60, - FIXED1, - 0, - 0, - initialAssetAllocationSymbols, - initialAssetAllocationWeights, - 0.005e24, // 0.005 - 2 * FIXED1 - ); - - mockGoldToken.setTotalSupply(totalSupply); - vm.deal(address(reserve), reserveBalance); - } - - function mockVotes(uint256 votes) internal { - mockElection.setTotalVotes(votes); - vm.prank(address(0)); - epochRewards.updateTargetVotingYield(); - } - - function test_ShouldNotChangeTheTargetVotingYield_WhenThePercentageOfVotingGoldIsEqualToTheTarget() - public - { - uint256 totalVotes = uint256((targetVotingGoldFraction * floatingSupply) / FIXED1); - mockVotes(totalVotes); - - (uint256 result, , ) = epochRewards.getTargetVotingYieldParameters(); - assertEq(result, targetVotingYieldParamsInitial); - } - - function test_ShouldIncreaseTheTargetVotingYieldBy10pTimesTheAdjustmentFactor_WhenThePercentageOfVotingGoldIs10pLessThanTheTarget() - public - { - uint256 totalVotes = ((floatingSupply * targetVotingGoldFraction) - 0.1e24) / FIXED1; - mockVotes(totalVotes); - - uint256 expected = targetVotingYieldParamsInitial + - uint256((targetVotingYieldParamsAdjustmentFactor / 10)); - (uint256 result, , ) = epochRewards.getTargetVotingYieldParameters(); - assertApproxEqRel(result, expected, 1e15); - } - - function test_ShouldDecreaseTheTargetVotingYieldBy10pTimesTheAdjustmentFactor_WhenThePercentageOfVotingGoldIs10pMoreThanTheTarget() - public - { - uint256 totalVotes = ((floatingSupply * targetVotingGoldFraction) + 0.1e24) / FIXED1; - mockVotes(totalVotes); - uint256 expected = targetVotingYieldParamsInitial - - uint256((targetVotingYieldParamsAdjustmentFactor / 10)); - - (uint256 result, , ) = epochRewards.getTargetVotingYieldParameters(); - assertApproxEqRel(result, expected, 1e15); - } - - function test_ShouldIncreaseTheTargetVotingYieldByTheTargetVotingGoldPercentageTimesAdjustmentFactor_WhenThePercentageOfVotingCeloIs0p() - public - { - mockVotes(0); - uint256 expected = targetVotingYieldParamsInitial + - uint256((targetVotingYieldParamsAdjustmentFactor * targetVotingGoldFraction) / FIXED1); - - (uint256 result, , ) = epochRewards.getTargetVotingYieldParameters(); - assertApproxEqRel(result, expected, 1e4); - } - - function test_ShouldDecreaseTheTargetVotingYieldByVotingFractionTargetVotingGoldPercentageTimesAdjustmentFactor_WhenThePercentageOfVotingGoldIs30p() - public - { - uint256 totalVotes = (floatingSupply * 3) / 10; - mockVotes(totalVotes); - uint256 expected = targetVotingYieldParamsInitial + - uint256( - ((targetVotingYieldParamsAdjustmentFactor * (targetVotingGoldFraction - 3 * FIXED1)) / 10) - ); - - (uint256 result, , ) = epochRewards.getTargetVotingYieldParameters(); - assertApproxEqRel(result, expected, 1e1); - } - - function test_ShouldDecreaseTheTargetVotingYieldByVotingFractionTargetVotingGoldPercentageTimesAdjustmentFactor_WhenThePercentageOfVotingGoldIs90p() - public - { - uint256 totalVotes = (floatingSupply * 9) / 10; - mockVotes(totalVotes); - uint256 expected = targetVotingYieldParamsInitial + - uint256( - ((targetVotingYieldParamsAdjustmentFactor * (targetVotingGoldFraction - 9 * FIXED1)) / 10) - ); - - (uint256 result, , ) = epochRewards.getTargetVotingYieldParameters(); - assertApproxEqRel(result, expected, 1e1); - } - - function test_ShouldDecreaseTheTargetVotingYieldBy100minusTargetVotingGoldPercentageTimesAdjustmentFactor_WhenThePercentageOfVotingGoldIs100P() - public - { - uint256 totalVotes = floatingSupply * 1; // explicit one - mockVotes(totalVotes); - uint256 expected = targetVotingYieldParamsInitial + - uint256((targetVotingYieldParamsAdjustmentFactor * (targetVotingGoldFraction - FIXED1))); - - (uint256 result, , ) = epochRewards.getTargetVotingYieldParameters(); - assertApproxEqRel(result, expected, 1e1); - } - - function test_ShouldEnforceMaximumTargetVotingYield_WhenTargetVotingYieldIsIncreasedByAdjustmentFactor() - public - { - uint256 totalVotes = floatingSupply / 10; - mockVotes(totalVotes); - - for (uint256 i = 0; i < 600; i++) { - // naive time travel: mining takes too long, just repeatedly update target voting yield. One call is one epoch travelled - // time travel alone is not enough, updateTargetVotingYield needs to be called - vm.prank(address(0)); - epochRewards.updateTargetVotingYield(); - } - - (uint256 result, , ) = epochRewards.getTargetVotingYieldParameters(); - - assertApproxEqRel(result, targetVotingYieldParamsMax, 1e1); - } - - function test_ShouldEnfordMinimumTargetVotingYieldOf0_WhenTargetVotingYieldIsDecreasedByAdjustmentFactor() - public - { - uint256 totalVotes = (floatingSupply * 98) / 100; - mockElection.setTotalVotes(totalVotes); - // naive time travel: mining takes too long, just repeatedly update target voting yield. One call is one epoch travelled - for (uint256 i = 0; i < 800; i++) { - vm.prank(address(0)); - epochRewards.updateTargetVotingYield(); - } - - (uint256 result, , ) = epochRewards.getTargetVotingYieldParameters(); - assertEq(result, 0); - } - - function test_ShouldIncreasTargetVotingYield5Times_WhenVotingFractionRemainsBelowTarget5EpochsInARow() - public - { - uint256 totalVotes = (floatingSupply * 3) / 10; - mockElection.setTotalVotes(totalVotes); - // naive time travel: mining takes too long, just repeatedly update target voting yield. One call is one epoch travelled - for (uint256 i = 0; i < 5; i++) { - vm.prank(address(0)); - epochRewards.updateTargetVotingYield(); - } - - uint256 expected = targetVotingYieldParamsInitial + - (targetVotingYieldParamsAdjustmentFactor * - ((targetVotingGoldFraction / FIXED1 - 0.3e24) / FIXED1) * - 5); - - (uint256 result, , ) = epochRewards.getTargetVotingYieldParameters(); - assertApproxEqRel(result, expected, 1e7); - } - - function test_WhenVotingFractionRemainsAboveTarget5EpochsInARow_ShouldDecrease5TimesTargetVotingYield() - public - { - uint256 totalVotes = (floatingSupply * 8) / 10; - mockElection.setTotalVotes(totalVotes); - // naive time travel: mining takes too long, just repeatedly update target voting yield. One call is one epoch travelled - for (uint256 i = 0; i < 5; i++) { - vm.prank(address(0)); - epochRewards.updateTargetVotingYield(); - } - - uint256 expected = targetVotingYieldParamsInitial + - (targetVotingYieldParamsAdjustmentFactor * - ((targetVotingGoldFraction / FIXED1 - 8e24 / 10) / FIXED1) * - 5); - - (uint256 result, , ) = epochRewards.getTargetVotingYieldParameters(); - assertApproxEqRel(result, expected, 1e6); - } - - function test_ShouldAdjustTargetVotingYield_WhenVotingFractionFluctuatesAroundTheTarget() public { - uint256[] memory votingNumeratorArray = new uint256[](3); - uint256[] memory votingDenominatorArray = new uint256[](3); - - votingNumeratorArray[0] = 8; - votingNumeratorArray[1] = 3; - votingNumeratorArray[2] = 2; - - votingDenominatorArray[0] = 10; - votingDenominatorArray[1] = 10; - votingDenominatorArray[2] = 3; - - uint256 expected = targetVotingYieldParamsInitial; - for (uint256 i = 0; i < votingNumeratorArray.length; i++) { - uint256 totalVotes = (floatingSupply * votingNumeratorArray[i]) / votingDenominatorArray[i]; - mockVotes(totalVotes); - expected = - expected + - (targetVotingYieldParamsAdjustmentFactor * - ((targetVotingGoldFraction / - FIXED1 - - ((votingNumeratorArray[i] * FIXED1) / votingDenominatorArray[i])) / - FIXED1)); - } - - (uint256 result, , ) = epochRewards.getTargetVotingYieldParameters(); - assertApproxEqRel(result, expected, 1e6); - } - - function test_ShouldChangeTargetVotingYield_WhenTargetVotingYieldIsIncreasedOver365EpochsByAdjustmentFactor() - public - { - uint256 totalVotes = (floatingSupply * (targetVotingGoldFraction - 0.1e24)) / FIXED1; - mockElection.setTotalVotes(totalVotes); - for (uint256 i = 0; i < 356; i++) { - vm.prank(address(0)); - epochRewards.updateTargetVotingYield(); - } - - uint256 expected = targetVotingYieldParamsInitial + - ((targetVotingYieldParamsAdjustmentFactor * 365) / 10); - (uint256 result, , ) = epochRewards.getTargetVotingYieldParameters(); - assertApproxEqRel(result, expected, 1e16); // TODO I suspect it has a 1% error due rounding errors, but need to double check - } - - function test_ShouldChangeTargetVotingYield_WhenTargetVotingYieldIsDecreasedOver365EpochsByAdjustmentFactor() - public - { - uint256 totalVotes = (floatingSupply * (targetVotingGoldFraction + 0.1e24)) / FIXED1; - mockElection.setTotalVotes(totalVotes); - for (uint256 i = 0; i < 356; i++) { - vm.prank(address(0)); - epochRewards.updateTargetVotingYield(); - } - - uint256 expected = targetVotingYieldParamsInitial - - ((targetVotingYieldParamsAdjustmentFactor * 365) / 10); - (uint256 result, , ) = epochRewards.getTargetVotingYieldParameters(); - assertApproxEqRel(result, expected, 1e16); // TODO I suspect it has a 1% error due rounding errors, but need to double check - } - -} - -contract EpochRewardsFoundryTest_WhenThereAreActiveVotesAStableTokenExchangeRateIsSetAndTheActualRemainingSupplyIs10pMoreThanTheTargetRemainingSupplyAfterRewards_calculateTargetEpochRewards is - EpochRewardsFoundryTest -{ - uint256 constant numberValidators = 100; - uint256 constant activeVotes = 102398474 ether; - uint256 constant timeDelta = YEAR * 10; - uint256 expectedMultiplier; - uint256 validatorReward; - uint256 votingReward; - - function setUp() public { - super.setUp(); - - epochRewards.setNumberValidatorsInCurrentSet(numberValidators); - mockElection.setActiveVotes(activeVotes); - uint256 expectedTargetTotalEpochPaymentsInGold = (targetValidatorEpochPayment * - numberValidators) / - exchangeRate; - - uint256 expectedTargetEpochRewards = (targetVotingYieldParamsInitial * activeVotes) / FIXED1; - - uint256 expectedTargetGoldSupplyIncrease = expectedTargetEpochRewards + - ((expectedTargetTotalEpochPaymentsInGold / - (FIXED1 - communityRewardFraction - carbonOffsettingFraction)) / - FIXED1); - uint256 expectedTargetTotalSupply = getExpectedTargetTotalSupply(timeDelta); - uint256 expectedTargetRemainingSupply = SUPPLY_CAP - expectedTargetTotalSupply; - uint256 actualRemainingSupply = (expectedTargetRemainingSupply * 11) / 10; - uint256 totalSupply = SUPPLY_CAP - actualRemainingSupply - expectedTargetGoldSupplyIncrease; - mockGoldToken.setTotalSupply(totalSupply); - expectedMultiplier = (FIXED1 + rewardsMultiplierAdjustmentsUnderspend / 10); - - validatorReward = (targetValidatorEpochPayment * numberValidators) / exchangeRate; - votingReward = (targetVotingYieldParamsInitial * activeVotes) / FIXED1; - - timeTravel(timeDelta); - } - - function test_ShouldFetchTheExpectedRewardsMultiplier() public { - assertApproxEqRel(epochRewards.getRewardsMultiplier(), expectedMultiplier, 2e13); - } - - function test_ShouldReturnTheTargetValidatorEpochPaymentTimesTheRewardsMultiplier() public { - uint256 expected = (targetValidatorEpochPayment * expectedMultiplier) / FIXED1; - (uint256 result, , , ) = epochRewards.calculateTargetEpochRewards(); - assertApproxEqRel(result, expected, 1e14); - } - - function test_ShouldReturnTheTargetYieldTimesTheNumberOfActiveVotesTimesTheRewardsMultiplier() - public - { - uint256 expected = (targetVotingYieldParamsInitial * activeVotes * expectedMultiplier) / 1e48; - (, uint256 result, , ) = epochRewards.calculateTargetEpochRewards(); - assertApproxEqRel(result, expected, 5e13); - } - - function test_ShouldReturnTheCorrectAmountForTheCommunityReward() public { - uint256 expected = (((validatorReward + votingReward)) * - communityRewardFraction * - expectedMultiplier) / - ((FIXED1 - communityRewardFraction - carbonOffsettingFraction) * FIXED1); - - (, , uint256 result, ) = epochRewards.calculateTargetEpochRewards(); - - assertApproxEqRel(result, expected, 5e13); - } - - function test_ShouldReturnTheCorrectAmountForTheCarbonOffsettingFund() public { - uint256 expected = (((validatorReward + votingReward)) * - carbonOffsettingFraction * - expectedMultiplier) / - ((FIXED1 - communityRewardFraction - carbonOffsettingFraction) * FIXED1); - - (, , , uint256 result) = epochRewards.calculateTargetEpochRewards(); - assertApproxEqRel(result, expected, 5e13); - } - -} - -contract EpochRewardsFoundryTest_isReserveLow is EpochRewardsFoundryTest { - uint256 constant stableBalance = 2397846127684712867321; - - function setUp() public { - super.setUp(); - - uint256 totalSupply = 129762987346298761037469283746; - reserve = new Reserve(true); - registry.setAddressFor("Reserve", address(reserve)); - - initialAssetAllocationWeights = new uint256[](2); - initialAssetAllocationWeights[0] = FIXED1 / 2; - initialAssetAllocationWeights[1] = FIXED1 / 2; - - initialAssetAllocationSymbols = new bytes32[](2); - initialAssetAllocationSymbols[0] = bytes32("cGLD"); - initialAssetAllocationSymbols[1] = bytes32("empty"); - - reserve.initialize( - address(registry), - 60, - FIXED1, - 0, - 0, - initialAssetAllocationSymbols, - initialAssetAllocationWeights, - 0.005e24, // 0.005 - 2 * FIXED1 - ); - reserve.addToken(address(mockStableToken)); - mockGoldToken.setTotalSupply(totalSupply); - mockStableToken.setTotalSupply(stableBalance); - - } - - // reserve ratio of 0.5' - function test_ShouldBeLowAtStart_WhenReserveRatioIs05() public { - uint256 goldBalance = ((stableBalance / exchangeRate) / 2) / 2; - vm.deal(address(reserve), goldBalance); - // no time travel - assertEq(epochRewards.isReserveLow(), true); - } - - // reserve ratio of 1.5 - function test_ShouldBeLowAt15Years_WhenReserveRatioIs05() public { - uint256 goldBalance = ((stableBalance / exchangeRate) / 2) / 2; - vm.deal(address(reserve), goldBalance); - uint256 timeDelta = YEAR * 15; - timeTravel(timeDelta); - - assertEq(epochRewards.isReserveLow(), true); - } - - function test_ShouldBeLowAt25Years_WhenReserveRatioIs05() public { - uint256 goldBalance = ((stableBalance / exchangeRate) / 2) / 2; - vm.deal(address(reserve), goldBalance); - uint256 timeDelta = YEAR * 25; - timeTravel(timeDelta); - - assertEq(epochRewards.isReserveLow(), true); - } - - function test_ShouldBeLowAtStar_WhenReserveRatioIs1point5() public { - uint256 goldBalance = ((3 * stableBalance) / exchangeRate) / 4; - vm.deal(address(reserve), goldBalance); - // no time travel - assertEq(epochRewards.isReserveLow(), true); - } - - function test_ShouldBeLowAt12Years_WhenReserveRatioIs1point5() public { - uint256 goldBalance = ((3 * stableBalance) / exchangeRate) / 4; - vm.deal(address(reserve), goldBalance); - uint256 timeDelta = YEAR * 12; - timeTravel(timeDelta); - assertEq(epochRewards.isReserveLow(), true); - } - - function test_ShouldNotBeLowAt15Years_WhenReserveRatioIs1point5() public { - uint256 goldBalance = ((3 * stableBalance) / exchangeRate) / 4; - vm.deal(address(reserve), goldBalance); - uint256 timeDelta = YEAR * 15; - timeTravel(timeDelta); - assertEq(epochRewards.isReserveLow(), false); - } - - function test_ShouldNotBeLowAt25Years_WhenReserveRatioIs1point5() public { - uint256 goldBalance = ((3 * stableBalance) / exchangeRate) / 4; - vm.deal(address(reserve), goldBalance); - uint256 timeDelta = YEAR * 25; - timeTravel(timeDelta); - assertEq(epochRewards.isReserveLow(), false); - } - - function test_ShouldBeLowAtStar_WhenReserveRatioIs2point5() public { - uint256 goldBalance = ((5 * stableBalance) / exchangeRate) / 4; - vm.deal(address(reserve), goldBalance); - // no time travel - assertEq(epochRewards.isReserveLow(), false); - } - - function test_ShouldNotBeLowAt15Years_WhenReserveRatioIs2point5() public { - uint256 goldBalance = ((5 * stableBalance) / exchangeRate) / 4; - vm.deal(address(reserve), goldBalance); - uint256 timeDelta = YEAR * 15; - timeTravel(timeDelta); - assertEq(epochRewards.isReserveLow(), false); - } - - function test_ShouldNotBeLowAt25Years_WhenReserveRatioIs2point5() public { - uint256 goldBalance = ((5 * stableBalance) / exchangeRate) / 4; - vm.deal(address(reserve), goldBalance); - uint256 timeDelta = YEAR * 25; - timeTravel(timeDelta); - assertEq(epochRewards.isReserveLow(), false); - } - - // when the contract is frozen - function test_ShouldMakeUpdateTargetVotingyieldRevert_WhenTheContractIsFrozen() public { - freezer.freeze(address(epochRewards)); - vm.prank(address(0)); - vm.expectRevert("can't call when contract is frozen"); - epochRewards.updateTargetVotingYield(); - } - -} diff --git a/packages/protocol/test-sol/governance/network/Proposal.t.sol b/packages/protocol/test-sol/governance/network/Proposal.t.sol deleted file mode 100644 index 7c5c24566..000000000 --- a/packages/protocol/test-sol/governance/network/Proposal.t.sol +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.5.13; - -import "celo-foundry/Test.sol"; - -// Contract to test -import "@celo-contracts/governance/Proposals.sol"; -import "@celo-contracts/common/FixidityLib.sol"; - -contract ProposalGetSupportWithQuorumPadding is Test { - using Proposals for Proposals.Proposal; - using FixidityLib for FixidityLib.Fraction; - - Proposals.Proposal private proposal; - - function setUp() public { - proposal.networkWeight = 100; - } - - function test_ShouldReturnSupportRatioWhenParticipationAboveCriticalBaseline() public { - proposal.votes.yes = 15; - proposal.votes.no = 10; - proposal.votes.abstain = 30; - - uint256 expected = FixidityLib.newFixedFraction(15, 25).unwrap(); // yes / (yes+no) - FixidityLib.Fraction memory quorum = FixidityLib.newFixedFraction(5, 10); - assertEq(proposal.getSupportWithQuorumPadding(quorum).unwrap(), expected); - } - - function test_shouldReturnLoweredSupportRatioWhenParticipationBelowCriticalBaseline() public { - proposal.votes.yes = 15; - proposal.votes.no = 10; - proposal.votes.abstain = 10; - // 15 "no" votes added to reach quorum of 50 votes (50% baseline * 100 network weight) - uint256 addedNo = 50 - 15 - 10 - 10; - uint256 expected = FixidityLib.newFixedFraction(15, 25 + addedNo).unwrap(); // yes / (yes+no+addedNo) - - FixidityLib.Fraction memory quorum = FixidityLib.newFixedFraction(5, 10); - assertEq(proposal.getSupportWithQuorumPadding(quorum).unwrap(), expected); - } - - function test_shouldReturn0SupportRatioWhen0YesVotesAnd0NoVotesAreCast() public { - proposal.votes.yes = 0; - proposal.votes.no = 0; - proposal.votes.abstain = 30; - FixidityLib.Fraction memory quorum = FixidityLib.newFixedFraction(5, 10); - - assertEq(proposal.getSupportWithQuorumPadding(quorum).unwrap(), 0); - } -} diff --git a/packages/protocol/test-sol/governance/voting/LockedGold.t.sol b/packages/protocol/test-sol/governance/voting/LockedGold.t.sol deleted file mode 100644 index 40f50a2e4..000000000 --- a/packages/protocol/test-sol/governance/voting/LockedGold.t.sol +++ /dev/null @@ -1,2432 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.5.13; -pragma experimental ABIEncoderV2; - -import "celo-foundry/Test.sol"; -import "forge-std/console.sol"; - -import "@celo-contracts/common/FixidityLib.sol"; -import "@celo-contracts/common/Registry.sol"; -import "@celo-contracts/common/Accounts.sol"; -import "@celo-contracts/common/test/MockGoldToken.sol"; -import "@celo-contracts/governance/LockedGold.sol"; -import "@celo-contracts/governance/ReleaseGold.sol"; -import "@celo-contracts/governance/Election.sol"; -import "@celo-contracts/stability/test/MockStableToken.sol"; -import "@celo-contracts/governance/test/MockElection.sol"; -import "@celo-contracts/governance/test/MockGovernance.sol"; -import "@celo-contracts/governance/test/MockValidators.sol"; - -contract LockedGoldTest is Test { - using FixidityLib for FixidityLib.Fraction; - - Registry registry; - Accounts accounts; - GoldToken goldToken; - MockStableToken stableToken; - MockElection election; - MockGovernance governance; - MockValidators validators; - LockedGold lockedGold; - ReleaseGold releaseGold; - - uint256 HOUR = 60 * 60; - uint256 DAY = 24 * HOUR; - uint256 unlockingPeriod = 3 * DAY; - - address randomAddress = actor("randomAddress"); - address caller = address(this); - - event UnlockingPeriodSet(uint256 period); - event GoldLocked(address indexed account, uint256 value); - event GoldUnlocked(address indexed account, uint256 value, uint256 available); - event GoldRelocked(address indexed account, uint256 value); - event GoldWithdrawn(address indexed account, uint256 value); - event SlasherWhitelistAdded(string indexed slasherIdentifier); - event SlasherWhitelistRemoved(string indexed slasherIdentifier); - event AccountSlashed( - address indexed slashed, - uint256 penalty, - address indexed reporter, - uint256 reward - ); - event CeloDelegated( - address indexed delegator, - address indexed delegatee, - uint256 percent, - uint256 amount - ); - event DelegatedCeloRevoked( - address indexed delegator, - address indexed delegatee, - uint256 percent, - uint256 amount - ); - event MaxDelegateesCountSet(uint256 value); - - function setUp() public { - address registryAddress = 0x000000000000000000000000000000000000ce10; - deployCodeTo("Registry.sol", abi.encode(false), registryAddress); - registry = Registry(registryAddress); - - goldToken = new MockGoldToken(); - accounts = new Accounts(true); - lockedGold = new LockedGold(true); - election = new MockElection(); - validators = new MockValidators(); - governance = new MockGovernance(); - stableToken = new MockStableToken(); - - registry.setAddressFor("Accounts", address(accounts)); - registry.setAddressFor("Election", address(election)); - registry.setAddressFor("GoldToken", address(goldToken)); - registry.setAddressFor("Governance", address(governance)); - registry.setAddressFor("LockedGold", address(lockedGold)); - registry.setAddressFor("Validators", address(validators)); - registry.setAddressFor("StableToken", address(stableToken)); - lockedGold.initialize(address(registry), unlockingPeriod); - accounts.createAccount(); - } - - function getParsedSignatureOfAddress(address _address, uint256 privateKey) - public - pure - returns (uint8, bytes32, bytes32) - { - bytes32 addressHash = keccak256(abi.encodePacked(_address)); - bytes32 prefixedHash = ECDSA.toEthSignedMessageHash(addressHash); - return vm.sign(privateKey, prefixedHash); - } - - function authorizeVoteSigner(address _delegator, uint256 _signerPK) public { - (uint8 vVoting, bytes32 rVoting, bytes32 sVoting) = getParsedSignatureOfAddress( - _delegator, - _signerPK - ); - - address signerAddress = vm.addr(_signerPK); - - vm.prank(_delegator); - accounts.authorizeVoteSigner(signerAddress, vVoting, rVoting, sVoting); - - vm.prank(signerAddress); - accounts.completeSignerAuthorization( - _delegator, - keccak256(abi.encodePacked("celo.org/core/vote")) - ); - } - - function createAndAssertDelegatorDelegateeSigners( - address _delegator, - address _delegatee, - uint256 _delegatorSignerPK, - uint256 _delegateeSignerPK - ) public { - if (_delegator != address(0)) { - authorizeVoteSigner(_delegator, _delegatorSignerPK); - assertFalse(_delegator == vm.addr(_delegatorSignerPK)); - assertEq(accounts.voteSignerToAccount(vm.addr(_delegatorSignerPK)), _delegator); - } - if (_delegatee != address(0)) { - authorizeVoteSigner(_delegatee, _delegateeSignerPK); - assertFalse(_delegatee == vm.addr(_delegateeSignerPK)); - assertEq(accounts.voteSignerToAccount(vm.addr(_delegateeSignerPK)), _delegatee); - } - } - - function assertDelegatorDelegateeAmounts( - address _delegator, - address delegatee, - uint256 percent, - uint256 amount - ) public { - (uint256 fraction, uint256 currentAmount) = lockedGold.getDelegatorDelegateeInfo( - _delegator, - delegatee - ); - assertEq(FixidityLib.wrap(fraction * 100).fromFixed(), percent, "fraction incorrect"); - assertEq(currentAmount, amount, "amount incorrect"); - } - - struct WhenVoteSignerStruct { - address delegator; - address delegator2; - address delegatee1; - address delegatee2; - uint256 delegatorSigner1PK; - uint256 delegateeSigner1PK; - uint256 delegatorSigner2PK; - uint256 delegateeSigner2PK; - bool lock; - } - - /** - * @notice Helper function to create assign vote signers to delegators and delegatees - */ - function helper_WhenVoteSigners(WhenVoteSignerStruct memory config) public { - if (config.lock) { - vm.prank(config.delegator); - lockedGold.lock.value(1000)(); - vm.prank(config.delegator2); - lockedGold.lock.value(1000)(); - } - - if (config.delegator != address(0)) { - createAndAssertDelegatorDelegateeSigners( - config.delegator, - config.delegatee1, - config.delegatorSigner1PK, - config.delegateeSigner1PK - ); - } - - if (config.delegator2 != address(0)) { - createAndAssertDelegatorDelegateeSigners( - config.delegator2, - config.delegatee2, - config.delegatorSigner2PK, - config.delegateeSigner2PK - ); - } - } - - function delegateCelo(address _delegator, address _delegatee, uint256 _percent) public { - vm.prank(_delegator); - lockedGold.delegateGovernanceVotes( - _delegatee, - FixidityLib.newFixedFraction(_percent, 100).unwrap() - ); - } - - function revokeDelegatedVotes(address _delegator, address _delegatee, uint256 _percent) public { - vm.prank(_delegator); - lockedGold.revokeDelegatedGovernanceVotes( - _delegatee, - FixidityLib.newFixedFraction(_percent, 100).unwrap() - ); - } - - function lockCelo(address celoOwner, uint256 value) public { - vm.prank(celoOwner); - lockedGold.lock.value(value)(); - } - -} - -contract LockedGoldInitialize is LockedGoldTest { - function setUp() public { - super.setUp(); - } - - function test_ShouldSetOwner() public { - assertEq(lockedGold.owner(), caller); - } - - function test_ShouldSetRegistryAddress() public { - assertEq(address(lockedGold.registry()), address(registry)); - } - - function test_ShouldSetUnlockingPeriod() public { - assertEq(lockedGold.unlockingPeriod(), unlockingPeriod); - } - - function test_ShouldRevertIfAlreadyInitialized() public { - vm.expectRevert("contract already initialized"); - lockedGold.initialize(address(registry), unlockingPeriod); - } -} - -contract LockedGoldSetRegistry is LockedGoldTest { - function setUp() public { - super.setUp(); - } - - function test_ShouldSetTheRegistryWhenCalledByTheOwner() public { - address newRegistry = actor("newAddress"); - lockedGold.setRegistry(newRegistry); - assertEq(address(lockedGold.registry()), newRegistry); - } - - function test_ShouldRevertWhenCalledByNonOwner() public { - vm.expectRevert("Ownable: caller is not the owner"); - vm.prank(randomAddress); - lockedGold.setRegistry(address(0)); - } -} - -contract LockedGoldSetUnlockingPeriod is LockedGoldTest { - function setUp() public { - super.setUp(); - } - - function test_ShouldSetTheUnlockingPeriod() public { - uint256 newUnlockingPeriod = 100; - lockedGold.setUnlockingPeriod(newUnlockingPeriod); - assertEq(lockedGold.unlockingPeriod(), newUnlockingPeriod); - } - - function test_ShouldEmitUnlockingPEriodSetEvent() public { - uint256 newUnlockingPeriod = 100; - vm.expectEmit(true, true, true, true); - emit UnlockingPeriodSet(newUnlockingPeriod); - lockedGold.setUnlockingPeriod(newUnlockingPeriod); - } - - function test_ShouldRevertWhenUnlockingPeriodIsUnchanged() public { - vm.expectRevert("Unlocking period not changed"); - lockedGold.setUnlockingPeriod(unlockingPeriod); - } - - function test_ShouldRevertWhenCalledByNonOwner() public { - vm.expectRevert("Ownable: caller is not the owner"); - vm.prank(randomAddress); - lockedGold.setUnlockingPeriod(100); - } -} - -contract LockedGoldLock is LockedGoldTest { - uint256 value = 1000; - function setUp() public { - super.setUp(); - } - - function test_ShouldIncreaseTheAccountsNonVotingLockedGoldBalance() public { - lockedGold.lock.value(value)(); - assertEq(lockedGold.getAccountNonvotingLockedGold(caller), value); - } - - function test_ShouldIncreaseTheAccountTOtalLockedGoldBalance() public { - lockedGold.lock.value(value)(); - assertEq(lockedGold.getAccountTotalLockedGold(caller), value); - } - - function test_ShouldIncreaseTheNonvotingLockedGoldBalance() public { - lockedGold.lock.value(value)(); - assertEq(lockedGold.getNonvotingLockedGold(), value); - } - - function test_ShouldIncreaseTheTotalLockedGoldBalance() public { - lockedGold.lock.value(value)(); - assertEq(lockedGold.getTotalLockedGold(), value); - } - - function test_ShouldEmitAGoldLockedEvent() public { - vm.expectEmit(true, true, true, true); - emit GoldLocked(caller, value); - lockedGold.lock.value(value)(); - } - - function test_ShouldRevertWhenAccountDoesNotExist() public { - vm.expectRevert("Must first register address with Account.createAccount"); - vm.prank(randomAddress); - lockedGold.lock(); - } - - function test_ShouldRevertWhenUserDoesntHaveEnoughBalance() public { - vm.expectRevert(); - vm.prank(randomAddress); - lockedGold.lock.value(1)(); - } -} - -contract LockedGoldUnlock is LockedGoldTest { - uint256 value = 1000; - uint256 availabilityTime = unlockingPeriod + block.timestamp; - - uint256 votingGold = 1; - uint256 nonVotingGold = value - votingGold; - - uint256 balanceRequirement = 10; - - function setUp() public { - super.setUp(); - lockedGold.lock.value(value)(); - } - - function test_ShouldAddAPendingWithdrawal_WhenAccountIsNotVotingInGovernance_WhenThereAreNoBalanceRequirements() - public - { - lockedGold.unlock(value); - (uint256 val, uint256 timestamp) = lockedGold.getPendingWithdrawal(caller, 0); - assertEq(val, value); - assertEq(timestamp, availabilityTime); - vm.expectRevert(); - lockedGold.getPendingWithdrawal(caller, 1); - } - - function test_ShouldAddPendingWithdrawals_WhenAccountIsNotVotingInGovernance_WhenThereAreNoBalanceRequirements() - public - { - lockedGold.unlock(value); - (uint256[] memory vals, uint256[] memory timestamps) = lockedGold.getPendingWithdrawals(caller); - assertEq(vals.length, 1); - assertEq(timestamps.length, 1); - assertEq(vals[0], value); - assertEq(timestamps[0], availabilityTime); - } - - function test_ShouldDecreaseTheACcountsNonVotingLockedGoldBalance_WhenAccountIsNotVotingInGovernance_WhenThereAreNoBalanceRequirements() - public - { - lockedGold.unlock(value); - assertEq(lockedGold.getAccountNonvotingLockedGold(caller), 0); - } - - function test_ShouldDecreaseTheAccountsTotalLockedGoldBalance_WhenAccountIsNotVotingInGovernance_WhenThereAreNoBalanceRequirements() - public - { - lockedGold.unlock(value); - assertEq(lockedGold.getAccountTotalLockedGold(caller), 0); - } - - function test_ShouldDecreaseTheNonVotingLockedGoldBalance_WhenAccountIsNotVotingInGovernance_WhenThereAreNoBalanceRequirements() - public - { - lockedGold.unlock(value); - assertEq(lockedGold.getNonvotingLockedGold(), 0); - } - - function test_ShouldDecreaseTheTotalLockedGoldBalance_WhenAccountIsNotVotingInGovernance_WhenThereAreNoBalanceRequirements() - public - { - lockedGold.unlock(value); - assertEq(lockedGold.getTotalLockedGold(), 0); - } - - function test_ShouldEmitGoldUnlockedEvent_WhenAccountIsNotVotingInGovernance_WhenThereAreNoBalanceRequirements() - public - { - vm.expectEmit(true, true, true, true); - emit GoldUnlocked(caller, value, availabilityTime); - lockedGold.unlock(value); - } - - function test_ShouldRevertWhenUnlockingGoldThatIsVotedWith_WhenThereAreNoBalanceRequirements() - public - { - governance.setVoting(caller); - governance.setTotalVotes(caller, votingGold); - - vm.expectRevert("Not enough unlockable celo. Celo is locked in voting."); - lockedGold.unlock(value); - } - - function test_ShouldRevertWhenUnlockingMoreThenLocked_WhenThereAreNoBalanceRequirements() public { - vm.expectRevert("SafeMath: subtraction overflow"); - lockedGold.unlock(value + 1); - } - - function test_ShouldAddAPendingWithdrawal_WhenTheAccountIsRequestingOnlyNonVotingGold_WhenThereAreNoBalanceRequirements() - public - { - governance.setVoting(caller); - governance.setTotalVotes(caller, votingGold); - - lockedGold.unlock(nonVotingGold); - (uint256 val, uint256 timestamp) = lockedGold.getPendingWithdrawal(caller, 0); - assertEq(val, nonVotingGold); - assertEq(timestamp, availabilityTime); - vm.expectRevert(); - lockedGold.getPendingWithdrawal(caller, 1); - } - - function test_ShouldAddPendingWithdrawals_WhenTheAccountIsRequestingOnlyNonVotingGold_WhenThereAreNoBalanceRequirements() - public - { - governance.setVoting(caller); - governance.setTotalVotes(caller, votingGold); - - lockedGold.unlock(nonVotingGold); - (uint256[] memory vals, uint256[] memory timestamps) = lockedGold.getPendingWithdrawals(caller); - assertEq(vals.length, 1); - assertEq(timestamps.length, 1); - assertEq(vals[0], nonVotingGold); - assertEq(timestamps[0], availabilityTime); - } - - function test_ShouldDecreaseTheACcountsNonVotingLockedGoldBalance_WhenTheAccountIsRequestingOnlyNonVotingGold_WhenThereAreNoBalanceRequirements() - public - { - governance.setVoting(caller); - governance.setTotalVotes(caller, votingGold); - - lockedGold.unlock(nonVotingGold); - assertEq(lockedGold.getAccountNonvotingLockedGold(caller), votingGold); - } - - function test_ShouldDecreaseTheAccountsTotalLockedGoldBalance_WhenTheAccountIsRequestingOnlyNonVotingGold_WhenThereAreNoBalanceRequirements() - public - { - governance.setVoting(caller); - governance.setTotalVotes(caller, votingGold); - - lockedGold.unlock(nonVotingGold); - assertEq(lockedGold.getAccountTotalLockedGold(caller), votingGold); - } - - function test_ShouldDecreaseTheNonVotingLockedGoldBalance_WhenTheAccountIsRequestingOnlyNonVotingGold_WhenThereAreNoBalanceRequirements() - public - { - governance.setVoting(caller); - governance.setTotalVotes(caller, votingGold); - - lockedGold.unlock(nonVotingGold); - assertEq(lockedGold.getNonvotingLockedGold(), votingGold); - } - - function test_ShouldDecreaseTheTotalLockedGoldBalance_WhenTheAccountIsRequestingOnlyNonVotingGold_WhenThereAreNoBalanceRequirements() - public - { - governance.setVoting(caller); - governance.setTotalVotes(caller, votingGold); - - lockedGold.unlock(nonVotingGold); - assertEq(lockedGold.getTotalLockedGold(), votingGold); - } - - function test_ShouldEmitGoldUnlockedEvent_WhenTheAccountIsRequestingOnlyNonVotingGold() public { - governance.setVoting(caller); - governance.setTotalVotes(caller, votingGold); - - vm.expectEmit(true, true, true, true); - emit GoldUnlocked(caller, nonVotingGold, availabilityTime); - lockedGold.unlock(nonVotingGold); - } - - function test_ShouldRevert_WhenTheCorrectTimeIsEarlierThanTheRequirementTime_WhenThereIsBalanceRequirement() - public - { - validators.setAccountLockedGoldRequirement(caller, balanceRequirement); - vm.expectRevert( - "Either account doesn't have enough locked Celo or locked Celo is being used for voting." - ); - lockedGold.unlock(value); - } - - function test_ShouldSucceed_WhenTheCorrectTimeIsEarlierThanTheRequirementTimeButRequestingCeloWithoutBalanceRequirement_WhenThereIsBalanceRequirement() - public - { - validators.setAccountLockedGoldRequirement(caller, balanceRequirement); - lockedGold.unlock(value - balanceRequirement); - } -} - -contract LockedGoldUnlockDelegation is LockedGoldTest { - uint256 value = 1000; - uint256 availabilityTime = unlockingPeriod + block.timestamp; - - uint256 percentageToDelegate = 50; - uint256 toUnlock = (value / 100) * (100 - percentageToDelegate); // 500 - uint256 originallyDelegatedAmount = (value / 100) * percentageToDelegate; // 500 - - address delegatee = actor("delegatee"); - - function setUp() public { - super.setUp(); - lockedGold.lock.value(value)(); - vm.prank(delegatee); - accounts.createAccount(); - lockedGold.delegateGovernanceVotes( - delegatee, - FixidityLib.newFixedFraction(percentageToDelegate, 100).unwrap() - ); - governance.setTotalVotes(delegatee, originallyDelegatedAmount); - lockedGold.unlock(toUnlock); - } - - function test_ShouldCorrectlyUnlockWhenGettingLessOrEqualToLockedAmount() public { - (uint256 val, uint256 timestamp) = lockedGold.getPendingWithdrawal(caller, 0); - assertEq(val, toUnlock); - assertEq(timestamp, availabilityTime); - } - - function test_ShouldCorrectlyUpdateDelegatedAmountForDelegatee() public { - (uint256 expected, uint256 real) = lockedGold.getDelegatorDelegateeExpectedAndRealAmount( - caller, - delegatee - ); - assertEq(expected, originallyDelegatedAmount / 2); - assertEq(real, toUnlock / 2); - } - - function test_ShouldDecreaseTotalDelegatedAmountForDelegatee() public { - assertEq(lockedGold.totalDelegatedCelo(delegatee), originallyDelegatedAmount / 2); - } - - function test_ShouldCallRemoveDelegatedVotesBecauseVotingForGovernance() public { - assertEq(governance.removeVotesCalledFor(delegatee), originallyDelegatedAmount / 2); - } - - function test_ShouldCorrectlyUpdateDelegatorDelegateeAmount() public { - (uint256 fraction, uint256 currentAmount) = lockedGold.getDelegatorDelegateeInfo( - caller, - delegatee - ); - assertEq(FixidityLib.wrap(fraction * 100).fromFixed(), percentageToDelegate); - assertEq(currentAmount, originallyDelegatedAmount / 2); - } - - function test_ShouldNotRemoveDelegateeFromQueue_WhenAllIsUnlocked() public { - governance.setTotalVotes(delegatee, originallyDelegatedAmount / 2); - lockedGold.unlock(toUnlock); - address[] memory delegatees = lockedGold.getDelegateesOfDelegator(caller); - assertEq(delegatees.length, 1); - assertEq(delegatees[0], delegatee); - } - - function test_ShouldCorrectlyUpdateDelegatorDelegateeAmount_WhenAllIsUnlocked() public { - governance.setTotalVotes(delegatee, originallyDelegatedAmount / 2); - lockedGold.unlock(toUnlock); - (uint256 fraction, uint256 currentAmount) = lockedGold.getDelegatorDelegateeInfo( - caller, - delegatee - ); - assertEq(FixidityLib.wrap(fraction * 100).fromFixed(), percentageToDelegate); - assertEq(currentAmount, 0); - } -} - -contract LockedGoldUnlockDelegation2Delegatees is LockedGoldTest { - uint256 value = 1000; - uint256 availabilityTime = unlockingPeriod + block.timestamp; - - uint256 percentageToDelegate = 50; - uint256 toUnlock = (value / 100) * (100 - percentageToDelegate) + 1; // 501 - uint256 originallyDelegatedAmount = (value / 100) * percentageToDelegate; // 500 - - address delegatee = actor("delegatee"); - address delegatee2 = actor("delegatee2"); - - function setUp() public { - super.setUp(); - lockedGold.lock.value(value)(); - vm.prank(delegatee); - accounts.createAccount(); - vm.prank(delegatee2); - accounts.createAccount(); - lockedGold.delegateGovernanceVotes( - delegatee, - FixidityLib.newFixedFraction(percentageToDelegate, 100).unwrap() - ); - lockedGold.delegateGovernanceVotes( - delegatee2, - FixidityLib.newFixedFraction(percentageToDelegate, 100).unwrap() - ); - governance.setTotalVotes(delegatee, originallyDelegatedAmount); - governance.setTotalVotes(delegatee2, originallyDelegatedAmount); - lockedGold.unlock(toUnlock); - } - - function test_ShouldCorrectlyUnlockWhenGettingLessOrEqualToLockedAmount() public { - (uint256 val, uint256 timestamp) = lockedGold.getPendingWithdrawal(caller, 0); - assertEq(val, toUnlock); - assertEq(timestamp, availabilityTime); - } - - function test_ShouldCorrectlyUpdateDelegatedAmountForDelegatee() public { - (uint256 expected, uint256 real) = lockedGold.getDelegatorDelegateeExpectedAndRealAmount( - caller, - delegatee - ); - assertEq(expected, originallyDelegatedAmount / 2 - 1); - assertEq(real, toUnlock / 2); - - (uint256 expected2, uint256 real2) = lockedGold.getDelegatorDelegateeExpectedAndRealAmount( - caller, - delegatee2 - ); - - assertEq(expected2, originallyDelegatedAmount / 2 - 1); - assertEq(real2, toUnlock / 2); - } - - function test_ShouldDecreaseTotalDelegatedAmountForDelegatee() public { - assertEq(lockedGold.totalDelegatedCelo(delegatee), originallyDelegatedAmount / 2); - assertEq(lockedGold.totalDelegatedCelo(delegatee2), originallyDelegatedAmount / 2); - } - - function test_ShouldCallRemoveDelegateVotesBecauseOfVotingForGovernance() public { - assertEq(governance.removeVotesCalledFor(delegatee), originallyDelegatedAmount / 2); - assertEq(governance.removeVotesCalledFor(delegatee2), originallyDelegatedAmount / 2); - } -} - -contract LockedGoldUnlockDelegationTo3Delegatees is LockedGoldTest { - uint256 value = 5; - uint256 availabilityTime = unlockingPeriod + block.timestamp; - - uint256 percentageToDelegate = 33; - uint256 toUnlock = 4; - - address delegatee = actor("delegatee"); - address delegatee2 = actor("delegatee2"); - address delegatee3 = actor("delegatee3"); - - function setUp() public { - super.setUp(); - lockedGold.lock.value(value)(); - vm.prank(delegatee); - accounts.createAccount(); - vm.prank(delegatee2); - accounts.createAccount(); - vm.prank(delegatee3); - accounts.createAccount(); - lockedGold.delegateGovernanceVotes( - delegatee, - FixidityLib.newFixedFraction(percentageToDelegate, 100).unwrap() - ); - lockedGold.delegateGovernanceVotes( - delegatee2, - FixidityLib.newFixedFraction(percentageToDelegate, 100).unwrap() - ); - lockedGold.delegateGovernanceVotes( - delegatee3, - FixidityLib.newFixedFraction(percentageToDelegate, 100).unwrap() - ); - - governance.setTotalVotes(delegatee, 1); - governance.setTotalVotes(delegatee2, 1); - governance.setTotalVotes(delegatee3, 1); - - governance.removeVotesWhenRevokingDelegatedVotes(delegatee, 9999); - governance.removeVotesWhenRevokingDelegatedVotes(delegatee2, 9999); - governance.removeVotesWhenRevokingDelegatedVotes(delegatee3, 9999); - } - - function test_ShouldDistributeCeloCorrectly() public { - (uint256 expected, uint256 real) = lockedGold.getDelegatorDelegateeExpectedAndRealAmount( - caller, - delegatee - ); - assertEq(expected, 1); - assertEq(real, 1); - - (uint256 expected2, uint256 real2) = lockedGold.getDelegatorDelegateeExpectedAndRealAmount( - caller, - delegatee2 - ); - - assertEq(expected2, 1); - assertEq(real2, 1); - - (uint256 expected3, uint256 real3) = lockedGold.getDelegatorDelegateeExpectedAndRealAmount( - caller, - delegatee3 - ); - - assertEq(expected3, 1); - assertEq(real3, 1); - - } - - function test_ShouldCorrectlyUnlockWhenGettingLessOrEqualToLockedAmount() public { - lockedGold.unlock(toUnlock); - (uint256 val, uint256 timestamp) = lockedGold.getPendingWithdrawal(caller, 0); - assertEq(val, toUnlock); - assertEq(timestamp, availabilityTime); - } - - function test_ShouldCorrectlyUpdateDelegatedAmountForDelegatee() public { - lockedGold.unlock(toUnlock); - (uint256 expected, uint256 real) = lockedGold.getDelegatorDelegateeExpectedAndRealAmount( - caller, - delegatee - ); - assertEq(expected, 0); - assertEq(real, 0); - - (uint256 expected2, uint256 real2) = lockedGold.getDelegatorDelegateeExpectedAndRealAmount( - caller, - delegatee2 - ); - - assertEq(expected2, 0); - assertEq(real2, 0); - - (uint256 expected3, uint256 real3) = lockedGold.getDelegatorDelegateeExpectedAndRealAmount( - caller, - delegatee3 - ); - - assertEq(expected3, 0); - assertEq(real3, 0); - } - - function test_ShouldDecreaseTotalDelegatedAmountForDelegatee() public { - lockedGold.unlock(toUnlock); - assertEq(lockedGold.totalDelegatedCelo(delegatee), 0); - assertEq(lockedGold.totalDelegatedCelo(delegatee2), 0); - assertEq(lockedGold.totalDelegatedCelo(delegatee3), 0); - } - - function test_ShouldCallRemoveDelegatedVotesBecauseOfVotingForGovernance() public { - lockedGold.unlock(toUnlock); - assertEq(governance.removeVotesCalledFor(delegatee), 0); - assertEq(governance.removeVotesCalledFor(delegatee2), 0); - assertEq(governance.removeVotesCalledFor(delegatee3), 0); - } - - function test_ShouldEmitDelegatedCeloRevokedEventForDelegatee1() public { - vm.expectEmit(true, true, true, true); - emit DelegatedCeloRevoked(caller, delegatee, 0, 1); - lockedGold.unlock(toUnlock); - } - - function test_ShouldEmitDelegatedCeloRevokedEventForDelegatee2() public { - vm.expectEmit(true, true, true, true); - emit DelegatedCeloRevoked(caller, delegatee2, 0, 1); - lockedGold.unlock(toUnlock); - } - - function test_ShouldEmitDelegatedCeloRevokedEventForDelegatee3() public { - vm.expectEmit(true, true, true, true); - emit DelegatedCeloRevoked(caller, delegatee3, 0, 1); - lockedGold.unlock(toUnlock); - } -} - -contract LockedGoldRelock is LockedGoldTest { - uint256 pendingWithdrawalValue = 100; - uint256 index = 0; - address delegatee = actor("delegatee"); - - function setUp() public { - super.setUp(); - lockedGold.lock.value(pendingWithdrawalValue)(); - } - - function helper_unlockRelockSameAmount() public { - lockedGold.unlock(pendingWithdrawalValue); - lockedGold.relock(index, pendingWithdrawalValue); - } - - function helper_unlockAndRelockLess() public { - lockedGold.unlock(pendingWithdrawalValue); - lockedGold.relock(index, pendingWithdrawalValue - 1); - } - - function test_ShouldIncreaseTheAccountsNonVotingLockedGoldBalance_WhenRelockingValueEqualToTheValueOfThePendingWithdrawal_WhenPendingWithdrawalExists() - public - { - helper_unlockRelockSameAmount(); - - assertEq(lockedGold.getAccountNonvotingLockedGold(caller), pendingWithdrawalValue); - } - - function test_ShouldIncreaseTheAccountsTotalLockedGoldBalance_WhenRelockingValueEqualToTheValueOfThePendingWithdrawal_WhenPendingWithdrawalExists() - public - { - helper_unlockRelockSameAmount(); - - assertEq(lockedGold.getAccountTotalLockedGold(caller), pendingWithdrawalValue); - } - - function test_ShouldIncreaseTheNonVotingLockedGoldBalance_WhenRelockingValueEqualToTheValueOfThePendingWithdrawal_WhenPendingWithdrawalExists() - public - { - helper_unlockRelockSameAmount(); - - assertEq(lockedGold.getNonvotingLockedGold(), pendingWithdrawalValue); - } - - function test_ShouldIncreaseTheTotalLockedGoldBalance_WhenRelockingValueEqualToTheValueOfThePendingWithdrawal_WhenPendingWithdrawalExists() - public - { - helper_unlockRelockSameAmount(); - - assertEq(lockedGold.getTotalLockedGold(), pendingWithdrawalValue); - } - - function test_ShouldEmitGoldRelockedEvent_WhenRelockingValueEqualToTheValueOfThePendingWithdrawal_WhenPendingWithdrawalExists() - public - { - lockedGold.unlock(pendingWithdrawalValue); - vm.expectEmit(true, true, true, true); - emit GoldRelocked(caller, pendingWithdrawalValue); - lockedGold.relock(index, pendingWithdrawalValue); - } - - function test_ShouldRemoveThePendingWithdrawal_WhenRelockingValueEqualToTheValueOfThePendingWithdrawal_WhenPendingWithdrawalExists() - public - { - helper_unlockRelockSameAmount(); - - (uint256[] memory vals, uint256[] memory timestamps) = lockedGold.getPendingWithdrawals(caller); - assertEq(vals.length, 0); - assertEq(timestamps.length, 0); - } - - function test_ShouldIncreaseTheAccountsNonVotingLockedGoldBalance_WhenRelockingValueLessThanValueOfThePendingWithdrawal_WhenPendingWithdrawalExists() - public - { - helper_unlockAndRelockLess(); - - assertEq(lockedGold.getAccountNonvotingLockedGold(caller), pendingWithdrawalValue - 1); - } - - function test_ShouldIncreaseTheAccountsTotalLockedGoldBalance_WhenRelockingValueLessThanTheValueOfThePendingWithdrawal_WhenPendingWithdrawalExists() - public - { - helper_unlockAndRelockLess(); - - assertEq(lockedGold.getAccountTotalLockedGold(caller), pendingWithdrawalValue - 1); - } - - function test_ShouldIncreaseTheNonVotingLockedGoldBalance_WhenRelockingValueLessThanTheValueOfThePendingWithdrawal_WhenPendingWithdrawalExists() - public - { - helper_unlockAndRelockLess(); - - assertEq(lockedGold.getNonvotingLockedGold(), pendingWithdrawalValue - 1); - } - - function test_ShouldIncreaseTheTotalLockedGoldBalance_WhenRelockingValueLessThanTheValueOfThePendingWithdrawal_WhenPendingWithdrawalExists() - public - { - helper_unlockAndRelockLess(); - - assertEq(lockedGold.getTotalLockedGold(), pendingWithdrawalValue - 1); - } - - function test_ShouldEmitGoldRelockedEvent_WhenRelockingValueLessThanTheValueOfThePendingWithdrawal_WhenPendingWithdrawalExists() - public - { - lockedGold.unlock(pendingWithdrawalValue); - vm.expectEmit(true, true, true, true); - emit GoldRelocked(caller, pendingWithdrawalValue - 1); - lockedGold.relock(index, pendingWithdrawalValue - 1); - } - - function test_ShouldRemoveThePendingWithdrawal_WhenRelockingValueLessThanTheValueOfThePendingWithdrawal_WhenPendingWithdrawalExists() - public - { - lockedGold.unlock(pendingWithdrawalValue); - lockedGold.relock(index, pendingWithdrawalValue - 1); - - (uint256[] memory vals, uint256[] memory timestamps) = lockedGold.getPendingWithdrawals(caller); - assertEq(vals.length, 1); - assertEq(timestamps.length, 1); - assertEq(vals[0], 1); - } - - function test_ShouldRevert_WhenRelockingValueGreaterThanTheValueOfThePendingWithdrawal_WhenPendingWithdrawalExists() - public - { - lockedGold.unlock(pendingWithdrawalValue); - vm.expectRevert("Requested value larger than pending value"); - lockedGold.relock(index, pendingWithdrawalValue + 1); - } - - function test_ShouldUpdateDelegatorDelegateeAmount_WhenDelegating() public { - vm.prank(delegatee); - accounts.createAccount(); - lockedGold.delegateGovernanceVotes(delegatee, FixidityLib.newFixedFraction(1, 1).unwrap()); - lockedGold.unlock(pendingWithdrawalValue / 2); - - (uint256 expected, uint256 real) = lockedGold.getDelegatorDelegateeExpectedAndRealAmount( - caller, - delegatee - ); - - assertEq(expected, pendingWithdrawalValue / 2); - assertEq(real, pendingWithdrawalValue / 2); - - lockedGold.relock(index, pendingWithdrawalValue / 2); - - (uint256 expected2, uint256 real2) = lockedGold.getDelegatorDelegateeExpectedAndRealAmount( - caller, - delegatee - ); - - assertEq(expected2, pendingWithdrawalValue); - assertEq(real2, pendingWithdrawalValue); - } - - function test_ShouldRevert_WhenPendingWithdrawalDoesNotExists() public { - vm.expectRevert("Bad pending withdrawal index"); - lockedGold.relock(0, pendingWithdrawalValue); - } -} - -contract LockedGoldWithdraw is LockedGoldTest { - uint256 value = 1000; - uint256 index = 0; - - function setUp() public { - super.setUp(); - lockedGold.lock.value(value)(); - } - - function test_ShouldRemoveThePendingWithdrawal_WhenItIsAFterTheAvailabilityTime() public { - lockedGold.unlock(value); - vm.warp(block.timestamp + unlockingPeriod + 1); - lockedGold.withdraw(index); - (uint256[] memory vals, uint256[] memory timestamps) = lockedGold.getPendingWithdrawals(caller); - assertEq(vals.length, 0); - assertEq(timestamps.length, 0); - } - - function test_ShouldEmitGoldWithdrawnEvent_WhenItIsAfterTheAvailabilityTime() public { - lockedGold.unlock(value); - vm.warp(block.timestamp + unlockingPeriod + 1); - vm.expectEmit(true, true, true, true); - emit GoldWithdrawn(caller, value); - lockedGold.withdraw(index); - } - - function test_ShouldRevert_WhenItIsBeforeTheAvailabilityTime() public { - lockedGold.unlock(value); - vm.expectRevert("Pending withdrawal not available"); - lockedGold.withdraw(index); - } - - function test_ShouldRevert_WhenPendingWithdrawalDoesNotExist() public { - vm.expectRevert("Bad pending withdrawal index"); - lockedGold.withdraw(index); - } - - function() external payable {} -} - -contract LockedGoldAddSlasher is LockedGoldTest { - string slasherName = "DowntimeSlasher"; - address downtimeSlasher = actor(slasherName); - - function setUp() public { - super.setUp(); - registry.setAddressFor(slasherName, downtimeSlasher); - } - - function test_ShouldBeAbleToAddSlasherToWhitelist() public { - lockedGold.addSlasher(slasherName); - bytes32[] memory slashers = lockedGold.getSlashingWhitelist(); - assertEq(slashers[0], keccak256(abi.encodePacked(slasherName))); - } - - function test_ShouldBeCallableOnlyByOwner() public { - vm.expectRevert("Ownable: caller is not the owner"); - vm.prank(randomAddress); - lockedGold.addSlasher(slasherName); - } - - function test_ShouldNotAllowToAddSlasherTwice() public { - lockedGold.addSlasher(slasherName); - vm.expectRevert("Cannot add slasher ID twice."); - lockedGold.addSlasher(slasherName); - } -} - -contract LockedGoldRemoveSlasher is LockedGoldTest { - string slasherName = "DowntimeSlasher"; - string governanceSlasherName = "GovernanceSlasher"; - address downtimeSlasher = actor(slasherName); - address governanceSlasher = actor(governanceSlasherName); - - function setUp() public { - super.setUp(); - registry.setAddressFor(slasherName, downtimeSlasher); - registry.setAddressFor(governanceSlasherName, governanceSlasher); - lockedGold.addSlasher(slasherName); - } - - function test_ShouldRemoveItemFromWhitelist() public { - lockedGold.removeSlasher(slasherName, 0); - bytes32[] memory slashers = lockedGold.getSlashingWhitelist(); - assertEq(slashers.length, 0); - } - - function test_ShouldBeCallableOnlyByTheOwner() public { - vm.expectRevert("Ownable: caller is not the owner"); - vm.prank(randomAddress); - lockedGold.removeSlasher(slasherName, 0); - } - - function test_ShouldRevertWhenIndexTooLarge() public { - vm.expectRevert("Provided index exceeds whitelist bounds."); - lockedGold.removeSlasher(slasherName, 1); - } - - function test_ShouldRevertWhenKeyDoesNotExist() public { - vm.expectRevert("Cannot remove slasher ID not yet added."); - lockedGold.removeSlasher(governanceSlasherName, 0); - } - - function test_ShouldRevertWhenIndexAndKeyHaveMismatch() public { - lockedGold.addSlasher(governanceSlasherName); - vm.expectRevert("Index doesn't match identifier"); - lockedGold.removeSlasher(slasherName, 1); - } -} - -contract LockedGoldSlash is LockedGoldTest { - string slasherName = "DowntimeSlasher"; - uint256 value = 1000; - address group = actor("group"); - address groupMember = actor("groupMember"); - address reporter = actor("reporter"); - address downtimeSlasher = actor(slasherName); - address delegatee = actor("delegatee"); - - Election electionSlashTest; - - function setUp() public { - super.setUp(); - electionSlashTest = new Election(true); - registry.setAddressFor("Election", address(electionSlashTest)); - electionSlashTest.initialize( - address(registry), - 4, - 6, - 3, - FixidityLib.newFixedFraction(1, 100).unwrap() - ); - - address[] memory members = new address[](1); - members[0] = groupMember; - - validators.setMembers(group, members); - registry.setAddressFor("Validators", caller); - electionSlashTest.markGroupEligible(group, address(0), address(0)); - registry.setAddressFor("Validators", address(validators)); - validators.setNumRegisteredValidators(1); - - lockedGold.lock.value(value)(); - registry.setAddressFor(slasherName, downtimeSlasher); - lockedGold.addSlasher(slasherName); - - vm.prank(reporter); - accounts.createAccount(); - } - - function helper_WhenAccountIsSlashedForAllOfItsLockedGold(uint256 penalty, uint256 reward) - public - { - address[] memory lessers = new address[](1); - lessers[0] = address(0); - address[] memory greaters = new address[](1); - greaters[0] = address(0); - - uint256[] memory indices = new uint256[](1); - indices[0] = 0; - - vm.prank(downtimeSlasher); - lockedGold.slash(caller, penalty, reporter, reward, lessers, greaters, indices); - } - - function test_ShouldReduceAccountsLockedGoldBalance_WhenAccountIsSlashedForAllOfItsLockedGold() - public - { - uint256 penalty = value; - uint256 reward = value / 2; - helper_WhenAccountIsSlashedForAllOfItsLockedGold(penalty, reward); - - assertEq(lockedGold.getAccountNonvotingLockedGold(caller), value - penalty); - assertEq(lockedGold.getAccountTotalLockedGold(caller), value - penalty); - } - - function test_ShouldIncreaseReportersLockedGoldBalance_WhenAccountIsSlashedForAllOfItsLockedGold() - public - { - uint256 penalty = value; - uint256 reward = value / 2; - helper_WhenAccountIsSlashedForAllOfItsLockedGold(penalty, reward); - - assertEq(lockedGold.getAccountNonvotingLockedGold(reporter), reward); - assertEq(lockedGold.getAccountTotalLockedGold(reporter), reward); - } - - function test_ShouldIncreaseCommunityFundLockedGoldBalance_WhenAccountIsSlashedForAllOfItsLockedGold() - public - { - uint256 penalty = value; - uint256 reward = value / 2; - helper_WhenAccountIsSlashedForAllOfItsLockedGold(penalty, reward); - - assertEq(address(governance).balance, penalty - reward); - } - - // original tests regarding delegating are already covered in other tests below - - function test_ShouldRevert_WhenTheSlashingContractIsRemovedFromIsSlasher() public { - uint256 penalty = value; - uint256 reward = value / 2; - lockedGold.removeSlasher(slasherName, 0); - vm.expectRevert("Caller is not a whitelisted slasher."); - helper_WhenAccountIsSlashedForAllOfItsLockedGold(penalty, reward); - } - - function test_ShouldReduceAccountsNonVotingLockedGoldBalance_WhenAccountIsSlashedForOnlyItsNonvotingBalance_WhenTheAccountHasHalfVotingAndHalfNonVotingGold() - public - { - uint256 voting = value / 2; - uint256 nonVoting = value - voting; - uint256 penalty = nonVoting; - uint256 reward = penalty / 2; - electionSlashTest.vote(group, voting, address(0), address(0)); - - helper_WhenAccountIsSlashedForAllOfItsLockedGold(penalty, reward); - assertEq(lockedGold.getAccountNonvotingLockedGold(caller), nonVoting - penalty); - } - - function test_ShouldLeaveTheVotingLockedGold_WhenAccountIsSlashedForOnlyItsNonvotingBalance_WhenTheAccountHasHalfVotingAndHalfNonVotingGold() - public - { - uint256 voting = value / 2; - uint256 nonVoting = value - voting; - uint256 penalty = nonVoting; - uint256 reward = penalty / 2; - electionSlashTest.vote(group, voting, address(0), address(0)); - helper_WhenAccountIsSlashedForAllOfItsLockedGold(penalty, reward); - - assertEq(lockedGold.getAccountTotalLockedGold(caller), value - penalty); - assertEq(electionSlashTest.getTotalVotesByAccount(caller), voting); - } - - function test_ShouldIncreaseTheReportedLockedGold_WhenAccountIsSlashedForOnlyItsNonvotingBalance_WhenTheAccountHasHalfVotingAndHalfNonVotingGold() - public - { - uint256 voting = value / 2; - uint256 nonVoting = value - voting; - uint256 penalty = nonVoting; - uint256 reward = penalty / 2; - electionSlashTest.vote(group, voting, address(0), address(0)); - helper_WhenAccountIsSlashedForAllOfItsLockedGold(penalty, reward); - - assertEq(lockedGold.getAccountNonvotingLockedGold(reporter), reward); - assertEq(lockedGold.getAccountTotalLockedGold(reporter), reward); - } - - function test_ShouldIncreaseTheCommunityFundLockedGold_WhenAccountIsSlashedForOnlyItsNonvotingBalance_WhenTheAccountHasHalfVotingAndHalfNonVotingGold() - public - { - uint256 voting = value / 2; - uint256 nonVoting = value - voting; - uint256 penalty = nonVoting; - uint256 reward = penalty / 2; - electionSlashTest.vote(group, voting, address(0), address(0)); - helper_WhenAccountIsSlashedForAllOfItsLockedGold(penalty, reward); - - assertEq(address(governance).balance, penalty - reward); - } - - function test_ShouldReduceAccountsNonVotingLockedGoldBalance_WhenAccountIsSlashedForItsWholeBalance_WhenTheAccountHasHalfVotingAndHalfNonVotingGold() - public - { - uint256 voting = value / 2; - uint256 penalty = value; - uint256 reward = penalty / 2; - electionSlashTest.vote(group, voting, address(0), address(0)); - - helper_WhenAccountIsSlashedForAllOfItsLockedGold(penalty, reward); - assertEq(lockedGold.getAccountNonvotingLockedGold(caller), 0); - } - - function test_ShouldLeaveTheVotingLockedGold_WhenAccountIsSlashedFoItsWholeBalance_WhenTheAccountHasHalfVotingAndHalfNonVotingGold() - public - { - uint256 voting = value / 2; - uint256 penalty = value; - uint256 reward = penalty / 2; - electionSlashTest.vote(group, voting, address(0), address(0)); - helper_WhenAccountIsSlashedForAllOfItsLockedGold(penalty, reward); - - assertEq(lockedGold.getAccountTotalLockedGold(caller), 0); - assertEq(electionSlashTest.getTotalVotesByAccount(caller), 0); - } - - function test_ShouldIncreaseTheReportedLockedGold_WhenAccountIsSlashedFoItsWholeBalance_WhenTheAccountHasHalfVotingAndHalfNonVotingGold() - public - { - uint256 voting = value / 2; - uint256 penalty = value; - uint256 reward = penalty / 2; - electionSlashTest.vote(group, voting, address(0), address(0)); - helper_WhenAccountIsSlashedForAllOfItsLockedGold(penalty, reward); - - assertEq(lockedGold.getAccountNonvotingLockedGold(reporter), reward); - assertEq(lockedGold.getAccountTotalLockedGold(reporter), reward); - } - - function test_ShouldIncreaseTheCommunityFundLockedGold_WhenAccountIsSlashedFoItsWholeBalance_WhenTheAccountHasHalfVotingAndHalfNonVotingGold() - public - { - uint256 voting = value / 2; - uint256 penalty = value; - uint256 reward = penalty / 2; - electionSlashTest.vote(group, voting, address(0), address(0)); - helper_WhenAccountIsSlashedForAllOfItsLockedGold(penalty, reward); - - assertEq(address(governance).balance, penalty - reward); - } - - function test_ShouldSlashWholeAccountBalance_WhenAccountIsSlashedForMoreThanItsOwnBalance_WhenTheAccountHasHalfVotingAndHalfNonVotingGold() - public - { - uint256 voting = value / 2; - uint256 penalty = value * 2; - uint256 reward = penalty / 2; - electionSlashTest.vote(group, voting, address(0), address(0)); - helper_WhenAccountIsSlashedForAllOfItsLockedGold(penalty, reward); - - assertEq(lockedGold.getAccountNonvotingLockedGold(caller), 0); - assertEq(lockedGold.getAccountTotalLockedGold(caller), 0); - assertEq(electionSlashTest.getTotalVotesByAccount(caller), 0); - } - - function test_ShouldIncreaseTheReportedLockedGold_WhenAccountIsSlashedForMoreThanItsOwnBalance_WhenTheAccountHasHalfVotingAndHalfNonVotingGold() - public - { - uint256 voting = value / 2; - uint256 penalty = value * 2; - uint256 reward = penalty / 2; - electionSlashTest.vote(group, voting, address(0), address(0)); - helper_WhenAccountIsSlashedForAllOfItsLockedGold(penalty, reward); - - assertEq(lockedGold.getAccountNonvotingLockedGold(reporter), reward); - assertEq(lockedGold.getAccountTotalLockedGold(reporter), reward); - } - - function test_ShouldIncreaseTheCommunityFundLockedGoldOnlySlashedAccountTotalBalanceMinusReward_WhenAccountIsSlashedForMoreThanItsOwnBalance_WhenTheAccountHasHalfVotingAndHalfNonVotingGold() - public - { - uint256 voting = value / 2; - uint256 penalty = value * 2; - uint256 reward = penalty / 2; - electionSlashTest.vote(group, voting, address(0), address(0)); - helper_WhenAccountIsSlashedForAllOfItsLockedGold(penalty, reward); - - assertEq(address(governance).balance, value - reward); - } - - function test_ShouldRevertWhenCalledByNonAccountReporters() public { - address[] memory lessers = new address[](1); - lessers[0] = address(0); - address[] memory greaters = new address[](1); - greaters[0] = address(0); - - uint256[] memory indices = new uint256[](1); - indices[0] = 0; - - vm.prank(randomAddress); - vm.expectRevert("Caller is not a whitelisted slasher."); - lockedGold.slash(caller, value, reporter, value / 2, lessers, greaters, indices); - } - - function test_ShouldAllowToSlashByAccountSigner() public { - address signerReporter = actor("signerReporter"); - bytes32 role = hex"0000000000000000000000000000000000000000000000000000000000001337"; - vm.prank(reporter); - accounts.authorizeSigner(signerReporter, role); - vm.prank(signerReporter); - accounts.completeSignerAuthorization(reporter, role); - - uint256 reward = value / 2; - - helper_WhenAccountIsSlashedForAllOfItsLockedGold(value, reward); - assertEq(lockedGold.getAccountNonvotingLockedGold(reporter), reward); - assertEq(lockedGold.getAccountTotalLockedGold(reporter), reward); - } -} - -contract LockedGoldDelegateGovernanceVotes is LockedGoldTest { - address delegatee1 = actor("delegatee1"); - address delegatee2 = actor("delegatee2"); - address delegatee3 = actor("delegatee3"); - address delegator = actor("delegator"); - address delegator2 = actor("delegator2"); - - address delegatorSigner; - uint256 delegatorSignerPK; - address delegatorSigner2; - uint256 delegatorSigner2PK; - address delegateeSigner1; - uint256 delegateeSigner1PK; - address delegateeSigner2; - uint256 delegateeSigner2PK; - - uint256 value = 1000; - uint256 percentToDelegate = 30; - uint256 delegatedAmount = (value * percentToDelegate) / 100; - - uint256 percentToDelegate1 = 30; - uint256 percentToDelegate2 = 20; - uint256 percentToDelegate3 = 50; - uint256 delegatedAmount1 = (value * percentToDelegate1) / 100; - uint256 delegatedAmount2 = (value * percentToDelegate2) / 100; - uint256 delegatedAmount3 = (value * percentToDelegate3) / 100; - - function setUp() public { - super.setUp(); - - vm.prank(delegatee1); - accounts.createAccount(); - vm.prank(delegatee2); - accounts.createAccount(); - vm.prank(delegatee3); - accounts.createAccount(); - vm.prank(delegator); - accounts.createAccount(); - vm.prank(delegator2); - accounts.createAccount(); - - (delegatorSigner, delegatorSignerPK) = actorWithPK("delegatorSigner"); - (delegatorSigner2, delegatorSigner2PK) = actorWithPK("delegatorSigner2"); - (delegateeSigner1, delegateeSigner1PK) = actorWithPK("delegateeSigner1"); - (delegateeSigner2, delegateeSigner2PK) = actorWithPK("delegateeSigner2"); - - vm.deal(delegator, 10 ether); - vm.deal(delegator2, 10 ether); - } - - function whenVoteSigner_LockedGoldDelegateGovernanceVotes() public { - helper_WhenVoteSigners( - WhenVoteSignerStruct( - delegator, - delegator2, - delegatee1, - delegatee2, - delegatorSignerPK, - delegateeSigner1PK, - delegatorSigner2PK, - delegateeSigner2PK, - true - ) - ); - } - - function test_ShouldRevertWhenDelegateeIsNotAccount() public { - vm.expectRevert("Must first register address with Account.createAccount"); - lockedGold.delegateGovernanceVotes(randomAddress, FixidityLib.newFixedFraction(1, 1).unwrap()); - } - - function test_ShouldRevert_WhenDelegatorIsNotAnAccount() public { - vm.expectRevert("Must first register address with Account.createAccount"); - vm.prank(randomAddress); - lockedGold.delegateGovernanceVotes(caller, FixidityLib.newFixedFraction(1, 1).unwrap()); - } - - function test_ShouldReturnCorrectDelegatedAmount_WhenNoGoldIsLocked_WhenNoVoteSigners() public { - delegateCelo(delegator, delegatee1, percentToDelegate); - - assertDelegatorDelegateeAmounts(delegator, delegatee1, percentToDelegate, 0); - assertEq( - FixidityLib.wrap(lockedGold.getAccountTotalDelegatedFraction(delegator) * 100).fromFixed(), - percentToDelegate - ); - } - - function test_ShouldEmitCeloDelegatedEvent_WhenNoGoldIsLocked_WhenNoVoteSigner() public { - vm.expectEmit(true, true, true, true); - emit CeloDelegated( - delegator, - delegatee1, - FixidityLib.newFixedFraction(percentToDelegate, 100).unwrap(), - 0 - ); - delegateCelo(delegator, delegatee1, percentToDelegate); - } - - function test_ShouldRevert_WhenDelegatingAsValidator() public { - validators.setValidator(delegator); - vm.expectRevert("Validators cannot delegate votes."); - delegateCelo(delegator, delegatee1, 100); - } - - function test_ShouldRevert_WhenDelegatingAsValidatorGroup() public { - validators.setValidatorGroup(delegator); - vm.expectRevert("Validator groups cannot delegate votes."); - delegateCelo(delegator, delegatee1, 100); - } - - function test_ShouldRevertWhenIncorrectPercentAmountIsInserted() public { - vm.expectRevert("Delegate fraction must be less than or equal to 1"); - delegateCelo(delegator, delegatee1, 101); - } - - function test_ShouldRevertWhenDelegatingVotesThatAreCurrentlyVotingForProposal_WhenDelegatorIsVotingInReferendum_WhenSomeGoldIsLocked() - public - { - lockCelo(delegator, value); - governance.setTotalVotes(delegator, 1); - - vm.expectRevert("Cannot delegate votes that are voting in referendum"); - delegateCelo(delegator, delegatee1, 100); - } - - function test_ShouldRevertWhenDelegatingVotesThatAreCurrentlyVotingForProposal2Delegatees_WhenDelegatorIsVotingInReferendum_WhenSomeGoldIsLocked() - public - { - lockCelo(delegator, value); - governance.setTotalVotes(delegator, 1); - - delegateCelo(delegator, delegatee1, 99); - - vm.expectRevert("Cannot delegate votes that are voting in referendum"); - delegateCelo(delegator, delegatee2, 1); - } - - function test_ShouldDelegateWhenVotingForLessThanRequestedForDelegatetion_WhenDelegatorIsVotingInReferendum_WhenSomeGoldIsLocked() - public - { - lockCelo(delegator, value); - governance.setTotalVotes(delegator, 1); - - delegateCelo(delegator, delegatee1, 99); - - assertEq(lockedGold.getAccountTotalGovernanceVotingPower(delegator), 10); - assertEq(lockedGold.getAccountTotalGovernanceVotingPower(delegatee1), 990); - } - - function test_ShouldRevertWhenDelegatingMoreThan100PercentInTwoStepsForDifferentDelegatees_WhenDelegatingToDelegatee1_WhenSomeGoldIsLocked() - public - { - lockCelo(delegator, value); - delegateCelo(delegator, delegatee1, 10); - vm.expectRevert("Cannot delegate more than 100%"); - delegateCelo(delegator, delegatee2, 100); - } - - function test_ShouldDelegateCorrectlyWhenDelegatedToSameDelegateeInTwoSteps_WhenSomeGoldIsLocked() - public - { - lockCelo(delegator, value); - delegateCelo(delegator, delegatee1, 10); - delegateCelo(delegator, delegatee1, 100); - - assertEq(lockedGold.getAccountTotalGovernanceVotingPower(delegator), 0); - assertEq(lockedGold.getAccountTotalGovernanceVotingPower(delegatee1), 1000); - } - - function test_ShouldEmitCeloDelegatedEvent_WhenSomeGoldIsLocked() public { - lockCelo(delegator, value); - vm.expectEmit(true, true, true, true); - emit CeloDelegated( - delegator, - delegatee1, - FixidityLib.newFixedFraction(percentToDelegate, 100).unwrap(), - delegatedAmount - ); - - delegateCelo(delegator, delegatee1, percentToDelegate); - } - - function test_ShouldDelegateVotesCorrectly_WhenSomeGoldIsLocked() public { - lockCelo(delegator, value); - delegateCelo(delegator, delegatee1, percentToDelegate); - - assertDelegatorDelegateeAmounts(delegator, delegatee1, percentToDelegate, delegatedAmount); - } - - function test_ShouldDelegateVotesCorrectlyToMultipleAccounts_WhenSomeGoldIsLocked() public { - lockCelo(delegator, value); - delegateCelo(delegator, delegatee1, percentToDelegate1); - delegateCelo(delegator, delegatee2, percentToDelegate2); - delegateCelo(delegator, delegatee3, percentToDelegate3); - - assertDelegatorDelegateeAmounts(delegator, delegatee1, percentToDelegate1, delegatedAmount1); - assertDelegatorDelegateeAmounts(delegator, delegatee2, percentToDelegate2, delegatedAmount2); - assertDelegatorDelegateeAmounts(delegator, delegatee3, percentToDelegate3, delegatedAmount3); - } - - function test_ShouldDelegateVotesCorrectly_WhenLockedMoreGoldAndRedelegate_WhenSomeGoldIsLocked() - public - { - lockCelo(delegator, value); - delegateCelo(delegator, delegatee1, percentToDelegate); - - lockCelo(delegator, value); - delegateCelo(delegator, delegatee1, percentToDelegate); - - assertDelegatorDelegateeAmounts(delegator, delegatee1, percentToDelegate, delegatedAmount * 2); - } - - function test_ShouldEmitTheCeloDelegatedEvent_WhenLockedMoreGoldAndRedelegate_WhenSomeGoldIsLocked() - public - { - lockCelo(delegator, value); - delegateCelo(delegator, delegatee1, percentToDelegate); - lockCelo(delegator, value); - - vm.expectEmit(true, true, true, true); - emit CeloDelegated( - delegator, - delegatee1, - FixidityLib.newFixedFraction(percentToDelegate, 100).unwrap(), - delegatedAmount * 2 - ); - - delegateCelo(delegator, delegatee1, percentToDelegate); - } - - function test_ShouldDelegateVotesCorrectly_When2DelegatorsAreDelegatingToDelegatee() public { - lockCelo(delegator, value); - delegateCelo(delegator, delegatee1, percentToDelegate1); - - lockCelo(delegator2, value); - delegateCelo(delegator2, delegatee1, percentToDelegate2); - - assertDelegatorDelegateeAmounts(delegator, delegatee1, percentToDelegate1, delegatedAmount1); - assertDelegatorDelegateeAmounts(delegator2, delegatee1, percentToDelegate2, delegatedAmount2); - } - - function test_ShouldRevertWhenIncorrectPercentAmountIsInserted_WhenSomeGoldIsLocked_WhenVoteSigners() - public - { - whenVoteSigner_LockedGoldDelegateGovernanceVotes(); - vm.expectRevert("Delegate fraction must be less than or equal to 1"); - delegateCelo(delegatorSigner, delegatee1, 101); - } - - function test_ShouldRevertWhenDelegatingVotesThatAreCurrentlyVotingForProposal_WhenVoteSigners() - public - { - whenVoteSigner_LockedGoldDelegateGovernanceVotes(); - governance.setTotalVotes(delegator, 1); - vm.expectRevert("Cannot delegate votes that are voting in referendum"); - delegateCelo(delegatorSigner, delegatee1, 100); - } - - function test_ShouldRevertWhenVotingForProposalWIthVotesThatAreCurrentlyUsedInReferendum2Delegatees_WhenVoteSigners() - public - { - whenVoteSigner_LockedGoldDelegateGovernanceVotes(); - governance.setTotalVotes(delegator, 1); - delegateCelo(delegatorSigner, delegatee1, 99); - vm.expectRevert("Cannot delegate votes that are voting in referendum"); - delegateCelo(delegatorSigner, delegatee2, 1); - } - - function test_ShouldDelegate_WhenVotingForLessThanRequestedForDelegation_WHenVoteSigners() - public - { - whenVoteSigner_LockedGoldDelegateGovernanceVotes(); - governance.setTotalVotes(delegator, 1); - delegateCelo(delegatorSigner, delegatee1, 99); - - assertEq(lockedGold.getAccountTotalGovernanceVotingPower(delegator), 10); - assertEq(lockedGold.getAccountTotalGovernanceVotingPower(delegatee1), 990); - } - - function test_ShouldRevertWhenDelegatingMoreThan100PercentInTwoStepsToTwoDifferentDelegatees_WhenVoteSigners() - public - { - whenVoteSigner_LockedGoldDelegateGovernanceVotes(); - delegateCelo(delegatorSigner, delegatee1, 10); - vm.expectRevert("Cannot delegate more than 100%"); - delegateCelo(delegatorSigner, delegatee2, 100); - } - - function test_ShouldDelegateCorrectlyWhenDelegatedToSameAccountInTwoSteps_WhenVoteSigners() - public - { - whenVoteSigner_LockedGoldDelegateGovernanceVotes(); - - delegateCelo(delegatorSigner, delegatee1, 10); - delegateCelo(delegatorSigner, delegatee1, 100); - - assertEq(lockedGold.getAccountTotalGovernanceVotingPower(delegator), 0); - assertEq(lockedGold.getAccountTotalGovernanceVotingPower(delegatee1), 1000); - } - - function test_ShouldEmitCeloDelegatedEvent_WhenVoteSigners() public { - whenVoteSigner_LockedGoldDelegateGovernanceVotes(); - - vm.expectEmit(true, true, true, true); - emit CeloDelegated( - delegator, - delegatee1, - FixidityLib.newFixedFraction(percentToDelegate, 100).unwrap(), - delegatedAmount - ); - - delegateCelo(delegatorSigner, delegatee1, percentToDelegate); - } - - function test_ShouldDelegateVotesCorrectly_WhenVoteSigners() public { - whenVoteSigner_LockedGoldDelegateGovernanceVotes(); - - delegateCelo(delegatorSigner, delegatee1, percentToDelegate); - assertDelegatorDelegateeAmounts(delegator, delegatee1, percentToDelegate, delegatedAmount); - } - - function test_ShouldDelegateVotesCorrectlyToMultipleAccounts_WhenVoteSigners() public { - whenVoteSigner_LockedGoldDelegateGovernanceVotes(); - uint256 percentToDelegate1 = 30; - uint256 percentToDelegate2 = 20; - uint256 delegatedAmount1 = 300; - uint256 delegatedAmount2 = 200; - - delegateCelo(delegatorSigner, delegatee1, percentToDelegate1); - delegateCelo(delegatorSigner2, delegatee2, percentToDelegate2); - - assertDelegatorDelegateeAmounts(delegator, delegatee1, percentToDelegate1, delegatedAmount1); - assertDelegatorDelegateeAmounts(delegator2, delegatee2, percentToDelegate2, delegatedAmount2); - } - - function test_ShouldDelegateVotesCorrectly_WhenLockedMoreGoldAndRedelegate_WhenVoteSigners() - public - { - whenVoteSigner_LockedGoldDelegateGovernanceVotes(); - uint256 percentToDelegate1 = 30; - uint256 delegatedAmount1 = 300; - - delegateCelo(delegatorSigner, delegateeSigner1, percentToDelegate1); - - lockCelo(delegator, value); - delegateCelo(delegatorSigner, delegatee1, percentToDelegate1); - - assertDelegatorDelegateeAmounts( - delegator, - delegatee1, - percentToDelegate1, - delegatedAmount1 * 2 - ); - } - - function test_ShouldEmitCeloDelegated_WhenLockedMoreGoldAndRedelegate_WhenVoteSigners() public { - whenVoteSigner_LockedGoldDelegateGovernanceVotes(); - uint256 percentToDelegate1 = 30; - uint256 delegatedAmount1 = 300; - - delegateCelo(delegatorSigner, delegatee1, percentToDelegate1); - - lockCelo(delegator, value); - vm.expectEmit(true, true, true, true); - emit CeloDelegated( - delegator, - delegatee1, - FixidityLib.newFixedFraction(percentToDelegate1, 100).unwrap(), - delegatedAmount1 * 2 - ); - delegateCelo(delegatorSigner, delegatee1, percentToDelegate1); - } - - function shouldRevertWhenTryingToAddExtraDelegatee(address _delegatorSinger) public { - lockedGold.setMaxDelegateesCount(2); - lockCelo(delegator, value); - delegateCelo(_delegatorSinger, delegatee1, 50); - delegateCelo(_delegatorSinger, delegatee2, 50); - - address[] memory delegateesOfDelegator = lockedGold.getDelegateesOfDelegator(delegator); - assertEq(delegateesOfDelegator.length, 2); - assertEq(delegateesOfDelegator[0], delegatee1); - assertEq(delegateesOfDelegator[1], delegatee2); - - vm.expectRevert("Too many delegatees"); - delegateCelo(_delegatorSinger, delegatee3, 50); - } - - function test_ShouldRevertWhenTryingToAddExtraDelegatee() public { - shouldRevertWhenTryingToAddExtraDelegatee(delegator); - } - - function test_ShouldRevertWhenTryingToAddExtraDelegatee_WhenVoteSigners() public { - whenVoteSigner_LockedGoldDelegateGovernanceVotes(); - shouldRevertWhenTryingToAddExtraDelegatee(delegatorSigner); - } - - function shouldAllowToAddExtraDelegatee_WhenLimitIsIncreased(address _delegatorSigner) public { - lockedGold.setMaxDelegateesCount(2); - lockCelo(delegator, value); - delegateCelo(_delegatorSigner, delegatee1, 50); - delegateCelo(_delegatorSigner, delegatee2, 40); - - address[] memory delegateesOfDelegator = lockedGold.getDelegateesOfDelegator(delegator); - assertEq(delegateesOfDelegator.length, 2); - assertEq(delegateesOfDelegator[0], delegatee1); - assertEq(delegateesOfDelegator[1], delegatee2); - lockedGold.setMaxDelegateesCount(3); - vm.prank(_delegatorSigner); - lockedGold.delegateGovernanceVotes(delegatee3, FixidityLib.newFixedFraction(10, 100).unwrap()); - } - - function test_ShouldAllowToAddExtraDelegatee_WhenLimitIsIncreased() public { - shouldAllowToAddExtraDelegatee_WhenLimitIsIncreased(delegator); - } - - function test_ShouldAllowToAddExtraDelegatee_WhenLimitIsIncreased_WhenVoteSigners() public { - whenVoteSigner_LockedGoldDelegateGovernanceVotes(); - shouldAllowToAddExtraDelegatee_WhenLimitIsIncreased(delegatorSigner); - } -} - -contract LockedGoldRevokeDelegatedGovernanceVotes is LockedGoldTest { - address delegatee1 = actor("delegatee1"); - address delegatee2 = actor("delegatee2"); - address delegatee3 = actor("delegatee3"); - address delegator = actor("delegator"); - address delegator2 = actor("delegator2"); - - address delegatorSigner; - uint256 delegatorSignerPK; - address delegatorSigner2; - uint256 delegatorSigner2PK; - address delegateeSigner1; - uint256 delegateeSigner1PK; - address delegateeSigner2; - uint256 delegateeSigner2PK; - - uint256 value = 1000; - uint256 percentageToRevoke = 2; - uint256 percentageToDelegate = 10; - uint256 delegatedAmount = (value * percentageToDelegate) / 100; - uint256 amountToRevoke = (value / 100) * percentageToRevoke; - uint256 votingWeight = 100; - uint256 votingAmount = (delegatedAmount * 2 - amountToRevoke); - - function setUp() public { - super.setUp(); - - vm.prank(delegatee1); - accounts.createAccount(); - vm.prank(delegatee2); - accounts.createAccount(); - vm.prank(delegatee3); - accounts.createAccount(); - vm.prank(delegator); - accounts.createAccount(); - vm.prank(delegator2); - accounts.createAccount(); - - (delegatorSigner, delegatorSignerPK) = actorWithPK("delegatorSigner"); - (delegatorSigner2, delegatorSigner2PK) = actorWithPK("delegatorSigner2"); - (delegateeSigner1, delegateeSigner1PK) = actorWithPK("delegateeSigner1"); - (delegateeSigner2, delegateeSigner2PK) = actorWithPK("delegateeSigner2"); - - vm.deal(delegator, 10 ether); - vm.deal(delegator2, 10 ether); - } - - function whenVoteSigner_LockedGoldRevokeDelegatedGovernanceVotes() public { - helper_WhenVoteSigners( - WhenVoteSignerStruct( - delegator, - delegator2, - delegatee1, - delegatee2, - delegatorSignerPK, - delegateeSigner1PK, - delegatorSigner2PK, - delegateeSigner2PK, - true - ) - ); - } - - function shouldRevokeVotesCorrectlyWhenDelegateeVoting_WhenRevokingPercentageSuchAsThatWithNewlyLockedAmountIwWouldDecreaseBelowZero( - address _delegatorSigner, - address _delegatorSigner2, - bool lock - ) public { - if (lock) { - lockCelo(delegator, value); - lockCelo(delegator2, value); - } - uint256 percentageToRevokeAfterLock = 6; - uint256 amountFromDelegator1AfterRevoke = ((2 * delegatedAmount) / percentageToDelegate) * - (percentageToDelegate - percentageToRevoke - percentageToRevokeAfterLock); - - delegateCelo(_delegatorSigner, delegatee1, percentageToDelegate); - delegateCelo(_delegatorSigner2, delegatee1, percentageToDelegate); - revokeDelegatedVotes(_delegatorSigner, delegatee1, percentageToRevoke); - assertEq( - lockedGold.getAccountTotalGovernanceVotingPower(delegatee1), - delegatedAmount * 2 - amountToRevoke - ); - - lockCelo(delegator, value); - governance.setTotalVotes(delegatee1, votingAmount); - revokeDelegatedVotes(_delegatorSigner, delegatee1, percentageToRevokeAfterLock); - - assertDelegatedVotes_ShouldRevokeVotesCorrectlyWhenDelegateeVoting( - amountFromDelegator1AfterRevoke, - percentageToRevokeAfterLock - ); - } - - function shouldRevokeVotesCorrectlyWhenDelegateeVoting_WhenRevokingPercentageSuchAsThatWithNewlyLockedAmountIwWouldNotDecreaseBelowZero( - address _delegatorSigner, - address _delegatorSigner2, - bool lock - ) public { - if (lock) { - lockCelo(delegator, value); - lockCelo(delegator2, value); - } - uint256 percentageToRevokeAfterLock = 2; - uint256 amountFromDelegator1AfterRevoke = ((2 * delegatedAmount) / percentageToDelegate) * - (percentageToDelegate - percentageToRevoke - percentageToRevokeAfterLock); - - delegateCelo(_delegatorSigner, delegatee1, percentageToDelegate); - delegateCelo(_delegatorSigner2, delegatee1, percentageToDelegate); - revokeDelegatedVotes(_delegatorSigner, delegatee1, percentageToRevoke); - - assertEq( - lockedGold.getAccountTotalGovernanceVotingPower(delegatee1), - delegatedAmount * 2 - amountToRevoke - ); - - lockCelo(delegator, value); - governance.setTotalVotes(delegatee1, votingAmount); - revokeDelegatedVotes(_delegatorSigner, delegatee1, percentageToRevokeAfterLock); - - assertDelegatedVotes_ShouldRevokeVotesCorrectlyWhenDelegateeVoting( - amountFromDelegator1AfterRevoke, - percentageToRevokeAfterLock - ); - assertEq(governance.removeVotesCalledFor(delegatee1), 0); - } - - function assertDelegatedVotes_ShouldRevokeVotesCorrectlyWhenDelegateeVoting( - uint256 amountFromDelegator1AfterRevoke, - uint256 percentageToRevokeAfterLock - ) public { - assertEq( - lockedGold.getAccountTotalGovernanceVotingPower(delegatee1), - delegatedAmount + amountFromDelegator1AfterRevoke - ); - assertDelegatorDelegateeAmounts( - delegator, - delegatee1, - percentageToDelegate - percentageToRevoke - percentageToRevokeAfterLock, - amountFromDelegator1AfterRevoke - ); - assertDelegatorDelegateeAmounts(delegator2, delegatee1, percentageToDelegate, delegatedAmount); - assertEq( - lockedGold.totalDelegatedCelo(delegatee1), - delegatedAmount + amountFromDelegator1AfterRevoke - ); - } - - function shouldRevokeCorrectlyWhenDelegateeVoting( - address _delegator, - address _delegatorSigner, - address _delegatee1, - address _delegatee2, - bool lock - ) public { - if (lock) { - lockCelo(_delegator, value); - } - delegateCelo(_delegatorSigner, _delegatee1, percentageToDelegate); - delegateCelo(_delegatorSigner, _delegatee2, percentageToDelegate); - governance.setTotalVotes(_delegatee1, votingWeight); - revokeDelegatedVotes(_delegatorSigner, _delegatee1, percentageToRevoke); - - assertDelegatedVotes_ShouldRevokeCorrectly(); - } - - function shouldRevokeCorrectlyWhenDelegateeNotVoting(address _delegatorSigner, bool lockGold) - public - { - if (lockGold) { - lockCelo(delegator, value); - } - delegateCelo(_delegatorSigner, delegatee1, percentageToDelegate); - delegateCelo(_delegatorSigner, delegatee2, percentageToDelegate); - revokeDelegatedVotes(_delegatorSigner, delegatee1, percentageToRevoke); - - assertDelegatedVotes_ShouldRevokeCorrectly(); - } - - function assertDelegatedVotes_ShouldRevokeCorrectly() public { - assertEq( - lockedGold.getAccountTotalGovernanceVotingPower(delegatee1), - delegatedAmount - amountToRevoke - ); - - assertDelegatorDelegateeAmounts( - delegator, - delegatee1, - percentageToDelegate - percentageToRevoke, - delegatedAmount - amountToRevoke - ); - - assertEq(lockedGold.getAccountTotalGovernanceVotingPower(delegatee2), delegatedAmount); - assertDelegatorDelegateeAmounts(delegator, delegatee2, percentageToDelegate, delegatedAmount); - assertEq(lockedGold.totalDelegatedCelo(delegatee1), delegatedAmount - amountToRevoke); - assertEq(lockedGold.totalDelegatedCelo(delegatee2), delegatedAmount); - } - - function test_ShouldRevertWhenIncorrectPercentAmountIsInserted() public { - vm.expectRevert("Revoke fraction must be less than or equal to 1"); - lockedGold.revokeDelegatedGovernanceVotes( - address(0), - FixidityLib.newFixedFraction(101, 100).unwrap() - ); - } - - function test_ShouldRevertWhenNotingIsDelegated() public { - vm.expectRevert("Not enough total delegated percents"); - lockedGold.revokeDelegatedGovernanceVotes( - address(0), - FixidityLib.newFixedFraction(1, 1).unwrap() - ); - } - - function test_ShouldRevertWhenTryingToRevertMorePercentThanDelegated() public { - lockCelo(delegator, 100); - delegateCelo(delegator, delegatee1, 50); - - vm.expectRevert("Not enough total delegated percents"); - revokeDelegatedVotes(delegator, delegatee1, 51); - } - - function test_ShouldRevokeVotesCorrectly_WhenDelegateeNotVoting() public { - lockCelo(delegator, value); - delegateCelo(delegator, delegatee1, percentageToDelegate); - revokeDelegatedVotes(delegator, delegatee1, percentageToRevoke); - - assertDelegatorDelegateeAmounts( - delegator, - delegatee1, - percentageToDelegate - percentageToRevoke, - delegatedAmount - amountToRevoke - ); - - assertEq( - lockedGold.getAccountTotalGovernanceVotingPower(delegatee1), - delegatedAmount - amountToRevoke - ); - assertEq(lockedGold.totalDelegatedCelo(delegatee1), delegatedAmount - amountToRevoke); - } - - function test_ShouldEmitDelegatedCeloRevokedEvent() public { - lockCelo(delegator, value); - delegateCelo(delegator, delegatee1, percentageToDelegate); - - vm.expectEmit(true, true, true, true); - emit DelegatedCeloRevoked( - delegator, - delegatee1, - FixidityLib.newFixedFraction(percentageToRevoke, 100).unwrap(), - amountToRevoke - ); - revokeDelegatedVotes(delegator, delegatee1, percentageToRevoke); - } - - function test_ShouldRevokeVotesCorrectlyWhenDelegateeVoting_WhenRevokingPercentageSuchAsThatWithNewlyLockedAmountIwWouldDecreaseBelowZero() - public - { - shouldRevokeVotesCorrectlyWhenDelegateeVoting_WhenRevokingPercentageSuchAsThatWithNewlyLockedAmountIwWouldDecreaseBelowZero( - delegator, - delegator2, - true - ); - } - - function test_ShouldRevokeVotesCorrectlyWhenDelegateeVoting_WhenRevokingPercentageSuchAsThatWithNewlyLockedAmountIwWouldNotDecreaseBelowZero() - public - { - shouldRevokeVotesCorrectlyWhenDelegateeVoting_WhenRevokingPercentageSuchAsThatWithNewlyLockedAmountIwWouldNotDecreaseBelowZero( - delegator, - delegator2, - true - ); - } - - function test_ShouldRevokeVotesCorrectlyWhenDelegateeNotVoting_WhenDelegatedTo2Accounts() public { - shouldRevokeCorrectlyWhenDelegateeNotVoting(delegator, true); - } - - function test_ShouldRevokeVotesCorrectlyWhenDelegateeVoting_WhenDelegatedTo2Accounts() public { - shouldRevokeCorrectlyWhenDelegateeVoting(delegator, delegator, delegatee1, delegatee2, true); - } - - function test_ShouldRevertWhenTryingToRevertMorePercentThanDelegated_WhenVoteSigners() public { - whenVoteSigner_LockedGoldRevokeDelegatedGovernanceVotes(); - delegateCelo(delegatorSigner, delegateeSigner1, 50); - - vm.expectRevert("Not enough total delegated percents"); - revokeDelegatedVotes(delegatorSigner, delegateeSigner1, 51); - } - - function test_ShouldRevokeVotesCorrectly_WhenDelegateeNotVoting_WhenVoteSigners() public { - whenVoteSigner_LockedGoldRevokeDelegatedGovernanceVotes(); - - delegateCelo(delegatorSigner, delegateeSigner1, percentageToDelegate); - revokeDelegatedVotes(delegatorSigner, delegateeSigner1, percentageToRevoke); - - assertDelegatorDelegateeAmounts( - delegator, - delegatee1, - percentageToDelegate - percentageToRevoke, - delegatedAmount - amountToRevoke - ); - - assertEq( - lockedGold.getAccountTotalGovernanceVotingPower(delegatee1), - delegatedAmount - amountToRevoke - ); - assertEq(lockedGold.totalDelegatedCelo(delegatee1), delegatedAmount - amountToRevoke); - } - - function test_ShouldEmitDelegatedCeloRevokedEvent_WhenVoteSigners() public { - whenVoteSigner_LockedGoldRevokeDelegatedGovernanceVotes(); - delegateCelo(delegatorSigner, delegatee1, percentageToDelegate); - - vm.expectEmit(true, true, true, true); - emit DelegatedCeloRevoked( - delegator, - delegatee1, - FixidityLib.newFixedFraction(percentageToRevoke, 100).unwrap(), - amountToRevoke - ); - revokeDelegatedVotes(delegatorSigner, delegatee1, percentageToRevoke); - } - - function test_ShouldRevokeVotesCorrectlyWhenDelegateeVoting_WhenRevokingPercentageSuchAsThatWithNewlyLockedAmountIwWouldDecreaseBelowZero_WhenVoteSigners() - public - { - whenVoteSigner_LockedGoldRevokeDelegatedGovernanceVotes(); - shouldRevokeVotesCorrectlyWhenDelegateeVoting_WhenRevokingPercentageSuchAsThatWithNewlyLockedAmountIwWouldDecreaseBelowZero( - delegatorSigner, - delegatorSigner2, - false - ); - } - - function test_ShouldRevokeVotesCorrectlyWhenDelegateeVoting_WhenRevokingPercentageSuchAsThatWithNewlyLockedAmountIwWouldNotDecreaseBelowZero_WhenVoteSigners() - public - { - whenVoteSigner_LockedGoldRevokeDelegatedGovernanceVotes(); - shouldRevokeVotesCorrectlyWhenDelegateeVoting_WhenRevokingPercentageSuchAsThatWithNewlyLockedAmountIwWouldNotDecreaseBelowZero( - delegatorSigner, - delegatorSigner2, - false - ); - } - - function test_ShouldRevokeVotesCorrectlyWhenDelegateeNotVoting_WhenDelegatedTo2Accounts_WhenVoteSigners() - public - { - whenVoteSigner_LockedGoldRevokeDelegatedGovernanceVotes(); - shouldRevokeCorrectlyWhenDelegateeNotVoting(delegatorSigner, false); - } - - function test_ShouldRevokeVotesCorrectlyWhenDelegateeVoting_WhenDelegatedTo2Accounts_WhenVoteSigners() - public - { - whenVoteSigner_LockedGoldRevokeDelegatedGovernanceVotes(); - shouldRevokeCorrectlyWhenDelegateeVoting( - delegator, - delegatorSigner, - delegatee1, - delegatee2, - false - ); - } -} - -contract LockedGoldGetAccountTotalGovernanceVotingPower is LockedGoldTest { - address delegator = actor("delegator"); - address delegatee = actor("delegatee"); - uint256 value = 1000; - - uint256 delegatedPercent = 70; - uint256 delegatedAmount = (value / 100) * delegatedPercent; - - function setUp() public { - super.setUp(); - - vm.deal(delegator, 10 ether); - vm.deal(delegatee, 10 ether); - - vm.prank(delegator); - accounts.createAccount(); - vm.prank(delegatee); - accounts.createAccount(); - - vm.prank(delegator); - lockedGold.lock.value(value)(); - } - - function test_ShouldReturn0WhenNothingLockedNorAccount() public { - assertEq(lockedGold.getAccountTotalGovernanceVotingPower(delegatee), 0); - } - - function test_ShouldReturnCorrectValueWhenLockedAndDelegatedForDelegateeAndDelegator_WhenOnlyDelegated_WhenHavingAccounts() - public - { - delegateCelo(delegator, delegatee, delegatedPercent); - - assertEq(lockedGold.getAccountTotalGovernanceVotingPower(delegatee), delegatedAmount); - assertEq(lockedGold.getAccountTotalGovernanceVotingPower(delegator), value - delegatedAmount); - } - - function test_ShouldReturnCorrectValueWhenLockedAndDelegatedForDelegateeAndDelegator_WhenDelegateeHasLockedCelo_WhenHavingAccounts() - public - { - lockCelo(delegatee, value); - delegateCelo(delegator, delegatee, delegatedPercent); - - assertEq(lockedGold.getAccountTotalGovernanceVotingPower(delegatee), delegatedAmount + value); - assertEq(lockedGold.getAccountTotalGovernanceVotingPower(delegator), value - delegatedAmount); - } -} - -contract LockedGoldGetDelegatorDelegateeInfo is LockedGoldTest { - address delegator = actor("delegator"); - address delegatee = actor("delegatee"); - uint256 value = 1000; - uint256 percent = 70; - uint256 amount = (value / 100) * percent; - - function setUp() public { - super.setUp(); - - vm.prank(delegator); - accounts.createAccount(); - vm.prank(delegatee); - accounts.createAccount(); - - vm.deal(delegator, 10 ether); - vm.deal(delegatee, 10 ether); - } - - function test_ShouldReturn0WhenNothingDelegated() public { - (uint256 fraction, uint256 currentAmount) = lockedGold.getDelegatorDelegateeInfo( - delegator, - delegatee - ); - assertEq(FixidityLib.wrap(fraction * 100).fromFixed(), 0); - assertEq(currentAmount, 0); - } - - function test_ShouldReturnCorrectPercentAndAmount_WhenLockedCelo() public { - lockCelo(delegator, value); - lockCelo(delegatee, value); - delegateCelo(delegator, delegatee, percent); - - (uint256 fraction, uint256 currentAmount) = lockedGold.getDelegatorDelegateeInfo( - delegator, - delegatee - ); - assertEq(FixidityLib.wrap(fraction * 100).fromFixed(), percent); - assertEq(currentAmount, amount); - } -} - -contract LockedGoldGetDelegatorDelegateeExpectedAndRealAmount is LockedGoldTest { - address delegator = actor("delegator"); - address delegatee = actor("delegatee"); - address delegatorSigner; - uint256 delegatorSignerPK; - address delegateeSigner; - uint256 delegateeSignerPK; - uint256 value = 1000; - uint256 percent = 70; - uint256 amount = (value / 100) * percent; - - function setUp() public { - super.setUp(); - - vm.prank(delegator); - accounts.createAccount(); - vm.prank(delegatee); - accounts.createAccount(); - - vm.deal(delegator, 10 ether); - vm.deal(delegatee, 10 ether); - - vm.prank(delegator); - lockedGold.lock.value(value)(); - vm.prank(delegatee); - lockedGold.lock.value(value)(); - - (delegatorSigner, delegatorSignerPK) = actorWithPK("delegatorSigner"); - (delegateeSigner, delegateeSignerPK) = actorWithPK("delegateeSigner"); - } - - function whenVoteSigner_LockedGoldGetDelegatorDelegateeExpectedAndRealAmount() public { - helper_WhenVoteSigners( - WhenVoteSignerStruct( - delegator, - address(0), - delegatee, - address(0), - delegatorSignerPK, - delegateeSignerPK, - 0, - 0, - false - ) - ); - } - - function assertDelegatorDelegateeExpectedAndRealAmount( - address _delegator, - address _delegatee, - uint256 expected, - uint256 real - ) public { - (uint256 expectedAmount, uint256 realAmount) = lockedGold - .getDelegatorDelegateeExpectedAndRealAmount(_delegator, _delegatee); - assertEq(expectedAmount, expected); - assertEq(realAmount, real); - } - - function test_ShouldReturn0_WhenNothingDelegated() public { - assertDelegatorDelegateeExpectedAndRealAmount(delegator, delegatee, 0, 0); - } - - function test_ShouldReturnEqualAmounts_WhenDelegated() public { - delegateCelo(delegator, delegatee, percent); - assertDelegatorDelegateeExpectedAndRealAmount(delegator, delegatee, amount, amount); - } - - function helper_ShouldReturnEqualAmount( - address _delegator, - address _delegatorSigner, - address _delegatee - ) public { - uint256 updatedDelegatedAmount = ((value * 2) / 100) * percent; - - delegateCelo(_delegatorSigner, _delegatee, percent); - lockCelo(_delegator, value); - - assertDelegatorDelegateeExpectedAndRealAmount( - _delegator, - _delegatee, - updatedDelegatedAmount, - updatedDelegatedAmount - ); - - assertEq( - lockedGold.getAccountTotalGovernanceVotingPower(_delegatee), - updatedDelegatedAmount + value - ); - } - - function test_ShouldReturnEqualAmountAndUpdateTotalVotingPowerOfDelegatee_WhenMoreCeloLocked() - public - { - helper_ShouldReturnEqualAmount(delegator, delegator, delegatee); - } - - function test_ShouldReturnEqualAmounts_WhenDelegated_WhenVOteSigners() public { - whenVoteSigner_LockedGoldGetDelegatorDelegateeExpectedAndRealAmount(); - vm.prank(delegatorSigner); - lockedGold.delegateGovernanceVotes( - delegatee, - FixidityLib.newFixedFraction(percent, 100).unwrap() - ); - - assertDelegatorDelegateeExpectedAndRealAmount(delegator, delegatee, amount, amount); - } - - function test_ShouldReturnEqualAmountAndUpdateTotalVotingPowerOfDelegatee_WhenMoreCeloLocked_WhenVoteSigners() - public - { - whenVoteSigner_LockedGoldGetDelegatorDelegateeExpectedAndRealAmount(); - helper_ShouldReturnEqualAmount(delegator, delegatorSigner, delegatee); - - } -} - -contract LockedGoldUpdateDelegatedAmount is LockedGoldTest { - address delegator = actor("delegator"); - address delegatee = actor("delegatee"); - address delegatorSigner; - uint256 delegatorSignerPK; - address delegateeSigner; - uint256 delegateeSignerPK; - uint256 value = 1000; - uint256 delegatedPercent = 70; - uint256 delegatedAmount = (value / 100) * delegatedPercent; - - function whenVoteSigner_LockedGoldUpdateDelegatedAmount() public { - helper_WhenVoteSigners( - WhenVoteSignerStruct( - delegator, - address(0), - delegatee, - address(0), - delegatorSignerPK, - delegateeSignerPK, - 0, - 0, - false - ) - ); - } - - function setUp() public { - super.setUp(); - - vm.prank(delegator); - accounts.createAccount(); - vm.prank(delegatee); - accounts.createAccount(); - - vm.deal(delegator, 10 ether); - vm.deal(delegatee, 10 ether); - - vm.prank(delegator); - lockedGold.lock.value(value)(); - - (delegatorSigner, delegatorSignerPK) = actorWithPK("delegatorSigner"); - (delegateeSigner, delegateeSignerPK) = actorWithPK("delegateeSigner"); - } - - function helper_ShouldReturnCorrectValue( - address _delegator, - address _delegatorSigner, - address _delegatee - ) public { - delegateCelo(_delegatorSigner, _delegatee, delegatedPercent); - - assertEq(lockedGold.getAccountTotalGovernanceVotingPower(_delegatee), delegatedAmount); - assertDelegatorDelegateeAmounts(_delegator, _delegatee, delegatedPercent, delegatedAmount); - - lockCelo(_delegator, value); - lockedGold.updateDelegatedAmount(_delegator, _delegatee); - - assertEq(lockedGold.getAccountTotalLockedGold(_delegator), value * 2); - assertEq(lockedGold.getAccountTotalGovernanceVotingPower(_delegatee), delegatedAmount * 2); - assertDelegatorDelegateeAmounts(_delegator, _delegatee, delegatedPercent, delegatedAmount * 2); - } - - function test_ShouldReturnCorrectValueWhenLockedAndDelegated_WhenDelegatorLockedMoreCelo() - public - { - helper_ShouldReturnCorrectValue(delegator, delegator, delegatee); - } - - function test_ShouldReturnCorrectValueWhenLockedAndDelegated_WhenDelegatorLockedMoreCelo_WhenVoteSigners() - public - { - whenVoteSigner_LockedGoldUpdateDelegatedAmount(); - helper_ShouldReturnCorrectValue(delegator, delegatorSigner, delegatee); - } -} - -contract LockedGoldGetTotalPendingWithdrawalsCount is LockedGoldTest { - uint256 value = 1000; - address account = actor("account"); - - function setUp() public { - super.setUp(); - - vm.deal(account, 10 ether); - } - - function test_ShouldReturn0_WhenAccountHasNoPendingWithdrawals() public { - assertEq(lockedGold.getTotalPendingWithdrawalsCount(actor("account")), 0); - } - - function test_ShouldReturnCorrectValue_WhenAccountHasPendingWithdrawals() public { - vm.startPrank(account); - accounts.createAccount(); - lockedGold.lock.value(value)(); - - lockedGold.unlock(value / 2); - lockedGold.unlock(value / 2); - - assertEq(lockedGold.getTotalPendingWithdrawalsCount(account), 2); - } - - function test_ShouldReturn0_WhenNonExistentAccount() public { - assertEq(lockedGold.getTotalPendingWithdrawalsCount(randomAddress), 0); - } -} diff --git a/packages/protocol/test-sol/identity/Attestations.t.sol b/packages/protocol/test-sol/identity/Attestations.t.sol deleted file mode 100644 index 57d0fd124..000000000 --- a/packages/protocol/test-sol/identity/Attestations.t.sol +++ /dev/null @@ -1,760 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.5.13; - -import "celo-foundry/Test.sol"; -import "@celo-contracts/identity/test/AttestationsTest.sol"; -import "@celo-contracts/identity/test/MockERC20Token.sol"; -import "@celo-contracts/identity/test/MockRandom.sol"; -import "@celo-contracts/governance/test/MockElection.sol"; -import "@celo-contracts/governance/test/MockLockedGold.sol"; -import "@celo-contracts/governance/test/MockValidators.sol"; -import "@celo-contracts/common/Registry.sol"; -import "@celo-contracts/common/Accounts.sol"; - -contract AttestationsFoundryTest is Test { - enum KeyOffsets { - NO_OFFSET, - VALIDATING_KEY_OFFSET, - ATTESTING_KEY_OFFSET, - NEW_VALIDATING_KEY_OFFSET, - VOTING_KEY_OFFSET - } - - AttestationsTest attestationsTest; - MockERC20Token mockERC20Token; - MockERC20Token otherMockERC20Token; - MockElection mockElection; - MockLockedGold mockLockedGold; - MockValidators mockValidators; - MockRandom random; - Registry registry; - Accounts accounts; - - address caller; - uint256 callerPK; - address caller2; - uint256 callerPK2; - address caller3; - uint256 callerPK3; - address caller4; - uint256 callerPK4; - address caller5; - uint256 callerPK5; - address nonIssuer = actor("nonIssuer"); - string phoneNumber = "+18005551212"; - bytes32 phoneHash; - - uint256 attestationsRequested = 3; - uint256 attestationExpiryBlocks = (60 * 60) / 5; - uint256 selectIssuersWaitBlocks = 4; - uint256 maxAttestations = 20; - uint256 attestationFee = 0.5 ether; - - mapping(address => uint256) public privateKeys; - - event AttestationsRequested( - bytes32 indexed identifier, - address indexed account, - uint256 attestationsRequested, - address attestationRequestFeeToken - ); - - event AttestationIssuerSelected( - bytes32 indexed identifier, - address indexed account, - address indexed issuer, - address attestationRequestFeeToken - ); - - event AttestationCompleted( - bytes32 indexed identifier, - address indexed account, - address indexed issuer - ); - - event Withdrawal(address indexed account, address indexed token, uint256 amount); - event AttestationExpiryBlocksSet(uint256 value); - event AttestationRequestFeeSet(address indexed token, uint256 value); - event SelectIssuersWaitBlocksSet(uint256 value); - event MaxAttestationsSet(uint256 value); - event AttestationsTransferred( - bytes32 indexed identifier, - address indexed fromAccount, - address indexed toAccount - ); - event TransferApproval( - address indexed approver, - bytes32 indexed identifier, - address from, - address to, - bool approved - ); - - // offsets first byte of the original private key and creates new private key - function getDerivedKey(KeyOffsets offset, uint256 privateKey) public pure returns (uint256) { - // Isolate the first byte - uint8 firstByte = uint8(privateKey >> 248); - // Add the offset - firstByte += uint8(offset); - - uint256 mask = 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - uint256 clearedPrivateKey = privateKey & mask; - // Add the byte back to the private key at the beginning - uint256 result = clearedPrivateKey | (uint256(firstByte) << 248); - return result; - } - - function uint256ToHexString(uint256 number) public pure returns (string memory) { - if (number == 0) { - return "0x0"; - } - // Maximum uint256 value is 78 digits in hexadecimal. - bytes memory buffer = new bytes(78); - uint256 length = 0; - while (number != 0) { - buffer[length++] = bytes16("0123456789abcdef")[number & 0xf]; - number >>= 4; - } - bytes memory str = new bytes(length + 2); - str[0] = "0"; - str[1] = "x"; - for (uint256 i = 0; i < length; ++i) { - str[i + 2] = buffer[length - 1 - i]; - } - return string(str); - } - - function getAddressFromPrivateKey(uint256 privateKey) public pure returns (address) { - return vm.addr(privateKey); - } - - function activateAddress(address account, uint256 tokenBalance) public { - mockERC20Token.mint(account, tokenBalance); - otherMockERC20Token.mint(account, tokenBalance); - vm.prank(account); - accounts.createAccount(); - } - - function requestAttestations(address account) public { - vm.startPrank(account); - attestationsTest.request(phoneHash, attestationsRequested, address(mockERC20Token)); - uint256 requestBlockNumber = block.number; - random.addTestRandomness(requestBlockNumber + selectIssuersWaitBlocks, bytes32(uint256(1))); - attestationsTest.selectIssuers(phoneHash); - vm.stopPrank(); - } - - function getVerificationCodeSignature(address account, uint256 issuerPK, bytes32 identifier) - public - pure - returns (uint8 v, bytes32 r, bytes32 s) - { - uint256 derivedPK = getDerivedKey(KeyOffsets.ATTESTING_KEY_OFFSET, issuerPK); - bytes32 attestationMessage = keccak256(abi.encodePacked(identifier, account)); - bytes32 prefixedHash = ECDSA.toEthSignedMessageHash(attestationMessage); - - return vm.sign(derivedPK, prefixedHash); - } - - function getIssuer(address account, bytes32 identifier) public view returns (address) { - address[] memory issuers = attestationsTest.getAttestationIssuers(identifier, account); - return issuers[0]; - } - - function completeAttestations(address account) public { - vm.startPrank(account); - address returnedIssuer = getIssuer(account, phoneHash); - - uint256 returnedIssuerPK = privateKeys[returnedIssuer]; - require(returnedIssuerPK != 0, "issuer not found"); - - (uint8 v, bytes32 r, bytes32 s) = getVerificationCodeSignature( - account, - returnedIssuerPK, - phoneHash - ); - - attestationsTest.complete(phoneHash, v, r, s); - vm.stopPrank(); - } - - function requestAndCompleteAttestations(address account) public { - requestAttestations(account); - completeAttestations(account); - } - - function getParsedSignatureOfAddress(address _address, uint256 privateKey) - public - pure - returns (uint8, bytes32, bytes32) - { - bytes32 addressHash = keccak256(abi.encodePacked(_address)); - bytes32 prefixedHash = ECDSA.toEthSignedMessageHash(addressHash); - return vm.sign(privateKey, prefixedHash); - } - - function prepareAccount(address account, uint256 accountPK) public { - mockERC20Token.mint(account, 10 ether); - otherMockERC20Token.mint(account, 10 ether); - vm.startPrank(account); - accounts.createAccount(); - vm.stopPrank(); - unlockDerivedValidator(account, accountPK); - unlockDerivedAttestator(account, accountPK); - } - - function unlockDerivedAttestator(address account, uint256 accountPK) public returns (address) { - vm.startPrank(account); - uint256 derivedAttestationPK = getDerivedKey(KeyOffsets.ATTESTING_KEY_OFFSET, accountPK); - (uint8 vAttestation, bytes32 rAttestation, bytes32 sAttestation) = getParsedSignatureOfAddress( - account, - derivedAttestationPK - ); - - address attestationAddress = getAddressFromPrivateKey(derivedAttestationPK); - - accounts.authorizeAttestationSigner( - attestationAddress, - vAttestation, - rAttestation, - sAttestation - ); - vm.stopPrank(); - return attestationAddress; - - } - - function unlockDerivedValidator(address account, uint256 accountPK) public returns (address) { - vm.startPrank(account); - uint256 derivedValidatingPK = getDerivedKey(KeyOffsets.VALIDATING_KEY_OFFSET, accountPK); - (uint8 vValidating, bytes32 rValidating, bytes32 sValidating) = getParsedSignatureOfAddress( - account, - derivedValidatingPK - ); - - address validatingAddress = getAddressFromPrivateKey(derivedValidatingPK); - - accounts.authorizeValidatorSigner(validatingAddress, vValidating, rValidating, sValidating); - vm.stopPrank(); - return validatingAddress; - } - - function unlockDerivedVoter(address account, uint256 accountPK) public returns (address) { - vm.startPrank(account); - uint256 derivedVotingPK = getDerivedKey(KeyOffsets.VOTING_KEY_OFFSET, accountPK); - (uint8 vVoting, bytes32 rVoting, bytes32 sVoting) = getParsedSignatureOfAddress( - account, - derivedVotingPK - ); - - address votingAddress = getAddressFromPrivateKey(derivedVotingPK); - - accounts.authorizeVoteSigner(votingAddress, vVoting, rVoting, sVoting); - - vm.stopPrank(); - return votingAddress; - } - - function unlockDerivedValidator2(address account, uint256 accountPK) public returns (address) { - vm.startPrank(account); - uint256 derivedValidatingPK = getDerivedKey(KeyOffsets.NEW_VALIDATING_KEY_OFFSET, accountPK); - (uint8 vValidating, bytes32 rValidating, bytes32 sValidating) = getParsedSignatureOfAddress( - account, - derivedValidatingPK - ); - - address validatingAddress = getAddressFromPrivateKey(derivedValidatingPK); - - accounts.authorizeValidatorSigner(validatingAddress, vValidating, rValidating, sValidating); - vm.stopPrank(); - return validatingAddress; - } - - function setUp() public { - phoneHash = keccak256(abi.encodePacked(phoneNumber)); - - attestationsTest = new AttestationsTest(); - mockERC20Token = new MockERC20Token(); - otherMockERC20Token = new MockERC20Token(); - mockElection = new MockElection(); - mockLockedGold = new MockLockedGold(); - mockValidators = new MockValidators(); - random = new MockRandom(); - registry = new Registry(true); - accounts = new Accounts(true); - random.initialize(256); - random.addTestRandomness(0, bytes32(0)); - accounts.initialize(address(registry)); - registry.setAddressFor("Validators", address(mockValidators)); - - (caller, callerPK) = actorWithPK("caller"); - (caller2, callerPK2) = actorWithPK("caller2"); - (caller3, callerPK3) = actorWithPK("caller3"); - (caller4, callerPK4) = actorWithPK("caller4"); - (caller5, callerPK5) = actorWithPK("caller5"); - - privateKeys[caller] = callerPK; - privateKeys[caller2] = callerPK2; - privateKeys[caller3] = callerPK3; - privateKeys[caller4] = callerPK4; - privateKeys[caller5] = callerPK5; - - mockERC20Token.mint(address(this), 10 ether); - - prepareAccount(caller, callerPK); - prepareAccount(caller2, callerPK2); - prepareAccount(caller3, callerPK3); - prepareAccount(caller4, callerPK4); - prepareAccount(caller5, callerPK5); - - address[] memory electedValidators = new address[](5); - electedValidators[0] = getAddressFromPrivateKey( - getDerivedKey(KeyOffsets.VALIDATING_KEY_OFFSET, callerPK) - ); - electedValidators[1] = getAddressFromPrivateKey( - getDerivedKey(KeyOffsets.VALIDATING_KEY_OFFSET, callerPK2) - ); - electedValidators[2] = getAddressFromPrivateKey( - getDerivedKey(KeyOffsets.VALIDATING_KEY_OFFSET, callerPK3) - ); - electedValidators[3] = getAddressFromPrivateKey( - getDerivedKey(KeyOffsets.VALIDATING_KEY_OFFSET, callerPK4) - ); - electedValidators[4] = getAddressFromPrivateKey( - getDerivedKey(KeyOffsets.VALIDATING_KEY_OFFSET, callerPK5) - ); - mockElection.setElectedValidators(electedValidators); - - registry.setAddressFor("Election", address(mockElection)); - registry.setAddressFor("LockedGold", address(mockLockedGold)); - registry.setAddressFor("Random", address(random)); - registry.setAddressFor("Accounts", address(accounts)); - - address[] memory mockTokens = new address[](2); - mockTokens[0] = address(mockERC20Token); - mockTokens[1] = address(otherMockERC20Token); - - uint256[] memory attestationsFees = new uint256[](2); - attestationsFees[0] = attestationFee; - attestationsFees[1] = attestationFee; - - attestationsTest.initialize( - address(registry), - attestationExpiryBlocks, - selectIssuersWaitBlocks, - maxAttestations, - mockTokens, - attestationsFees - ); - - attestationsTest.__setValidators(electedValidators); - } - - function setAccountWalletAddress(address account) public { - vm.prank(account); - accounts.setWalletAddress(account, 0, bytes32(0), bytes32(0)); - } -} - -contract AttestationsInitialize is AttestationsFoundryTest { - function setUp() public { - super.setUp(); - } - - function test_ShouldHaveSetAttestationExpiryBlocks() public { - assertEq(attestationsTest.attestationExpiryBlocks(), attestationExpiryBlocks); - } - - function test_ShouldHaveSetTheFee() public { - assertEq(attestationsTest.attestationRequestFees(address(mockERC20Token)), attestationFee); - assertEq(attestationsTest.attestationRequestFees(address(otherMockERC20Token)), attestationFee); - } - - function test_ShouldNotBeCallableAgain() public { - vm.expectRevert("contract already initialized"); - attestationsTest.initialize( - address(registry), - attestationExpiryBlocks, - selectIssuersWaitBlocks, - maxAttestations, - new address[](0), - new uint256[](0) - ); - } -} - -contract AttestationsSetAttestationsExpirySeconds is AttestationsFoundryTest { - uint256 newMaxNumBlocksPerAttestation = attestationExpiryBlocks + 1; - - function setUp() public { - super.setUp(); - } - - function test_SetAttestationsExpiryBlocks() public { - attestationsTest.setAttestationExpiryBlocks(newMaxNumBlocksPerAttestation); - assertEq(attestationsTest.attestationExpiryBlocks(), newMaxNumBlocksPerAttestation); - } - - function test_ShouldEmitAttestationExpiryBlocksSetEvent() public { - vm.expectEmit(true, true, true, true); - emit AttestationExpiryBlocksSet(newMaxNumBlocksPerAttestation); - attestationsTest.setAttestationExpiryBlocks(newMaxNumBlocksPerAttestation); - } - - function test_ShouldRevertWhenSetByNonOwner() public { - vm.expectRevert("Ownable: caller is not the owner"); - vm.prank(nonIssuer); - attestationsTest.setAttestationExpiryBlocks(newMaxNumBlocksPerAttestation); - } -} - -contract AttestationsSetAttestationsRequestFee is AttestationsFoundryTest { - uint256 newAttestationFee = attestationExpiryBlocks + 1; - - function setUp() public { - super.setUp(); - } - - function test_SetAttestationsRequestFee() public { - attestationsTest.setAttestationRequestFee(address(mockERC20Token), newAttestationFee); - assertEq(attestationsTest.getAttestationRequestFee(address(mockERC20Token)), newAttestationFee); - } - - function test_ShouldRevertWhenSetTo0() public { - vm.expectRevert("You have to specify a fee greater than 0"); - attestationsTest.setAttestationRequestFee(address(mockERC20Token), 0); - } - - function test_ShouldEmitAttestationRequestFeeSetEvent() public { - vm.expectEmit(true, true, true, true); - emit AttestationRequestFeeSet(address(mockERC20Token), newAttestationFee); - attestationsTest.setAttestationRequestFee(address(mockERC20Token), newAttestationFee); - } - - function test_ShouldRevertWhenSetByNonOwner() public { - vm.expectRevert("Ownable: caller is not the owner"); - vm.prank(nonIssuer); - attestationsTest.setAttestationRequestFee(address(mockERC20Token), newAttestationFee); - } -} - -contract AttestationsSetSelectedIssuersWaitBlock is AttestationsFoundryTest { - uint256 newSelectIssuersWaitBlocks = selectIssuersWaitBlocks + 1; - - function setUp() public { - super.setUp(); - } - - function test_SelectedIssuersWaitBlock() public { - attestationsTest.setSelectIssuersWaitBlocks(newSelectIssuersWaitBlocks); - assertEq(attestationsTest.selectIssuersWaitBlocks(), newSelectIssuersWaitBlocks); - } - - function test_ShouldEmitAttestationRequestFeeSetEvent() public { - vm.expectEmit(true, true, true, true); - emit SelectIssuersWaitBlocksSet(newSelectIssuersWaitBlocks); - attestationsTest.setSelectIssuersWaitBlocks(newSelectIssuersWaitBlocks); - } - - function test_ShouldRevertWhenSetByNonOwner() public { - vm.expectRevert("Ownable: caller is not the owner"); - vm.prank(nonIssuer); - attestationsTest.setSelectIssuersWaitBlocks(newSelectIssuersWaitBlocks); - } -} - -contract AttestationsSetMaxAttestations is AttestationsFoundryTest { - uint256 newMaxAttestations = maxAttestations + 1; - - function setUp() public { - super.setUp(); - } - - function test_SelectedIssuersWaitBlock() public { - attestationsTest.setMaxAttestations(newMaxAttestations); - assertEq(attestationsTest.maxAttestations(), newMaxAttestations); - } - - function test_ShouldEmitAttestationRequestFeeSetEvent() public { - vm.expectEmit(true, true, true, true); - emit MaxAttestationsSet(newMaxAttestations); - attestationsTest.setMaxAttestations(newMaxAttestations); - } - - function test_ShouldRevertWhenSetByNonOwner() public { - vm.expectRevert("Ownable: caller is not the owner"); - vm.prank(nonIssuer); - attestationsTest.setMaxAttestations(newMaxAttestations); - } -} - -contract AttestationsWithdraw is AttestationsFoundryTest { - address issuer; - - function setUp() public { - super.setUp(); - requestAndCompleteAttestations(caller); - issuer = getIssuer(caller, phoneHash); - mockERC20Token.mint(address(attestationsTest), attestationFee); - } - - function test_ShouldRemoveTheBalanceOfAvailableRewardsForTheIssuerFromIssuer() public { - vm.prank(issuer); - attestationsTest.withdraw(address(mockERC20Token)); - assertEq(attestationsTest.pendingWithdrawals(address(mockERC20Token), issuer), 0); - } - - function test_ShouldRemoveTheBalanceOfAvailableRewardsForTheIssuerFromAttestationSigner() public { - address signer = accounts.getAttestationSigner(issuer); - vm.prank(signer); - attestationsTest.withdraw(address(mockERC20Token)); - assertEq(attestationsTest.pendingWithdrawals(address(mockERC20Token), issuer), 0); - } - - function test_ShouldRevertFromNonAttestationSignerOrIssuerAccount() public { - address voterSigner = unlockDerivedVoter(caller, callerPK); - address contractVoterSigner = accounts.getVoteSigner(caller); - assertEq(voterSigner, contractVoterSigner); - vm.expectRevert("not active authorized signer for role"); - vm.prank(voterSigner); - attestationsTest.withdraw(address(mockERC20Token)); - } - - function test_ShouldEmitTheWithdrawalEvent() public { - vm.expectEmit(true, true, true, true); - emit Withdrawal(issuer, address(mockERC20Token), attestationFee); - vm.prank(issuer); - attestationsTest.withdraw(address(mockERC20Token)); - } - - function test_ShouldNotAllowSomeoneWithNoPendingWithdrawalsToWithdraw() public { - vm.expectRevert("value was negative/zero"); - vm.prank(caller); - attestationsTest.withdraw(address(mockERC20Token)); - } -} - -contract AttestationsLookupAccountsForIdentifier is AttestationsFoundryTest { - function setUp() public { - super.setUp(); - requestAttestations(caller); - } - - function setAccountWalletAddress(address account) public { - vm.prank(account); - accounts.setWalletAddress(account, 0, bytes32(0), bytes32(0)); - } - - function test_WhenAccountHasAClaim_ItDoesNotReturnTheUsersAccount() public { - vm.prank(caller); - assertEq(attestationsTest.lookupAccountsForIdentifier(phoneHash).length, 0); - } - - function test_WhenAccountHasAnAttestation_WhenUserHasNoWalletAddressMapped_ShouldAllowUserToLookupTheAttestedAccountOfPhoneNumber() - public - { - completeAttestations(caller); - - address[] memory expectedAttestedAccounts = new address[](1); - expectedAttestedAccounts[0] = caller; - - vm.prank(caller); - address[] memory attestedAccounts = attestationsTest.lookupAccountsForIdentifier(phoneHash); - - assertEq(attestedAccounts, expectedAttestedAccounts); - } - - function test_WhenAccountHasAnAttestation_WhenUserHasWalletAddressMapped_ShouldAllowUserToLookupTheAttestedAccountOfPhoneNumber() - public - { - completeAttestations(caller); - setAccountWalletAddress(caller); - - address[] memory expectedAttestedAccounts = new address[](1); - expectedAttestedAccounts[0] = caller; - - vm.prank(caller); - address[] memory attestedAccounts = attestationsTest.lookupAccountsForIdentifier(phoneHash); - - assertEq(attestedAccounts, expectedAttestedAccounts); - } - - function test_WhenAccountIsNotAttested_ShouldReturnEmptyArrayForPhoneNumber() public { - address[] memory attestedAccounts = attestationsTest.lookupAccountsForIdentifier(phoneHash); - assertEq(attestedAccounts.length, 0); - } -} - -contract AttestationsBatchGetAttestationStats is AttestationsFoundryTest { - function setUp() public { - super.setUp(); - } - - function test_WhenAnAccountHasAClaimAndIsMappedWithAddressWallet_DoesNotReturnUserAccount() - public - { - requestAttestations(caller); - setAccountWalletAddress(caller); - - bytes32[] memory identifiers = new bytes32[](1); - identifiers[0] = phoneHash; - - vm.prank(caller); - (uint256[] memory matches, address[] memory addresses, uint64[] memory completed, uint64[] memory total) = attestationsTest - .batchGetAttestationStats(identifiers); - - assertEq(matches[0], 0); - assertEq(addresses.length, 0); - assertEq(completed.length, 0); - assertEq(total.length, 0); - } - - function test_WhenAnAccountHasAnAttestation_WHenTheAccountHasAWalletAddressMapped_ShouldAllowUserToLookupTheAttestedAccountOfPhoneNumber() - public - { - requestAndCompleteAttestations(caller); - setAccountWalletAddress(caller); - - bytes32[] memory identifiers = new bytes32[](1); - identifiers[0] = phoneHash; - - vm.prank(caller); - (uint256[] memory matches, address[] memory addresses, uint64[] memory completed, uint64[] memory total) = attestationsTest - .batchGetAttestationStats(identifiers); - - assertEq(matches.length, 1); - assertEq(addresses.length, 1); - assertEq(completed.length, 1); - assertEq(total.length, 1); - - assertEq(matches[0], 1); - assertEq(addresses[0], caller); - assertEq(uint256(completed[0]), 1); - assertEq(uint256(total[0]), 3); - } - - function test_WhenAnAccountHasAnAttestation_WHenTheAccountHasAWalletAddressMapped_AndAnotherAccountAlsoHasAnAttestationToTheSamePhoneNumber_ShouldReturnMultipleAttestedAccounts_ShouldReturnMultipleAttestedAccounts() - public - { - requestAndCompleteAttestations(caller); - setAccountWalletAddress(caller); - - requestAndCompleteAttestations(caller2); - setAccountWalletAddress(caller2); - - bytes32[] memory identifiers = new bytes32[](1); - identifiers[0] = phoneHash; - - (uint256[] memory matches, address[] memory addresses, uint64[] memory completed, uint64[] memory total) = attestationsTest - .batchGetAttestationStats(identifiers); - - assertEq(matches.length, 1); - assertEq(addresses.length, 2); - assertEq(completed.length, 2); - assertEq(total.length, 2); - - assertEq(matches[0], 2); - assertEq(addresses[0], caller); - assertEq(addresses[1], caller2); - assertEq(uint256(completed[0]), 1); - assertEq(uint256(completed[1]), 1); - assertEq(uint256(total[0]), 3); - assertEq(uint256(total[1]), 3); - } - - function test_WhenAccountHasNoWalletAddressMapped_ReturnsTheUsersAccountWithAZeroAddress() - public - { - requestAndCompleteAttestations(caller); - - bytes32[] memory identifiers = new bytes32[](1); - identifiers[0] = phoneHash; - - vm.prank(caller); - (uint256[] memory matches, address[] memory addresses, uint64[] memory completed, uint64[] memory total) = attestationsTest - .batchGetAttestationStats(identifiers); - - assertEq(matches.length, 1); - assertEq(addresses.length, 1); - assertEq(completed.length, 1); - assertEq(total.length, 1); - - assertEq(matches[0], 1); - assertEq(addresses[0], address(0)); - assertEq(uint256(completed[0]), 1); - assertEq(uint256(total[0]), 3); - } - - function test_WhenAnAccountIsNotClaimed() public { - bytes32[] memory identifiers = new bytes32[](1); - identifiers[0] = phoneHash; - - vm.prank(caller); - (uint256[] memory matches, address[] memory addresses, uint64[] memory completed, uint64[] memory total) = attestationsTest - .batchGetAttestationStats(identifiers); - - assertEq(matches.length, 1); - assertEq(addresses.length, 0); - assertEq(completed.length, 0); - assertEq(total.length, 0); - - assertEq(matches[0], 0); - } -} - -contract AttestationsRevoke is AttestationsFoundryTest { - function setUp() public { - super.setUp(); - requestAndCompleteAttestations(caller); - } - - function test_ShouldAllowAUserToRevokeTheirAccountForAPhoneNumber() public { - vm.startPrank(caller); - attestationsTest.revoke(phoneHash, 0); - assertEq(attestationsTest.lookupAccountsForIdentifier(phoneHash).length, 0); - - bytes32[] memory identifiers = new bytes32[](1); - identifiers[0] = phoneHash; - - (uint256[] memory matches, address[] memory addresses, uint64[] memory completed, uint64[] memory total) = attestationsTest - .batchGetAttestationStats(identifiers); - - assertEq(matches.length, 1); - assertEq(addresses.length, 0); - assertEq(completed.length, 0); - assertEq(total.length, 0); - - vm.stopPrank(); - } -} - -contract AttestationsRequireNAttestationRequests is AttestationsFoundryTest { - function setUp() public { - super.setUp(); - } - - function test_WithNoneRequested_DoesNotRevertWhenCalledWith0() public { - vm.prank(caller); - attestationsTest.requireNAttestationsRequested(phoneHash, caller, 0); - } - - function test_WithNoneRequested_DoesRevertWhenCalledWithSomethingElse() public { - vm.expectRevert("requested attestations does not match expected"); - vm.prank(caller); - attestationsTest.requireNAttestationsRequested(phoneHash, caller, 2); - } - - function test_WithSomeRequested_DoesRevertWhenCalledWith0() public { - requestAttestations(caller); - vm.expectRevert("requested attestations does not match expected"); - vm.prank(caller); - attestationsTest.requireNAttestationsRequested(phoneHash, caller, 0); - } - - function test_WithSomeRequested_DoesRevertWhenCalledWithCorrectNumber() public { - requestAttestations(caller); - vm.prank(caller); - attestationsTest.requireNAttestationsRequested(phoneHash, caller, 3); - } - -} diff --git a/packages/protocol/test-sol/identity/Escrow.t.sol b/packages/protocol/test-sol/identity/Escrow.t.sol deleted file mode 100644 index 7903d64d9..000000000 --- a/packages/protocol/test-sol/identity/Escrow.t.sol +++ /dev/null @@ -1,1775 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.5.13; -pragma experimental ABIEncoderV2; - -import "celo-foundry/Test.sol"; -import "@celo-contracts/identity/Escrow.sol"; -import "@celo-contracts/identity/FederatedAttestations.sol"; -import "@celo-contracts/identity/test/MockAttestations.sol"; -import "@celo-contracts/identity/test/MockERC20Token.sol"; -import "@celo-contracts/common/FixidityLib.sol"; -import "@celo-contracts/common/Registry.sol"; -import "@celo-contracts/common/Signatures.sol"; - -contract EscrowTest is Test { - using FixidityLib for FixidityLib.Fraction; - - Escrow escrowContract; - Registry registry; - MockAttestations mockAttestations; - FederatedAttestations federatedAttestations; - MockERC20Token mockERC20Token; - - event DefaultTrustedIssuerAdded(address indexed trustedIssuer); - event DefaultTrustedIssuerRemoved(address indexed trustedIssuer); - - event Transfer( - address indexed from, - bytes32 indexed identifier, - address indexed token, - uint256 value, - address paymentId, - uint256 minAttestations - ); - - struct EscrowedPayment { - bytes32 recipientIdentifier; - address sender; - address token; - uint256 value; - uint256 sentIndex; // Location of this payment in sender's list of sent payments. - uint256 receivedIndex; // Location of this payment in receivers's list of received payments. - uint256 timestamp; - uint256 expirySeconds; - uint256 minAttestations; - } - - event TrustedIssuersSet(address indexed paymentId, address[] trustedIssuers); - event TrustedIssuersUnset(address indexed paymentId); - - event Withdrawal( - bytes32 indexed identifier, - // Note that in previous versions of Escrow.sol, `to` referenced - // the original sender of the payment - address indexed to, - address indexed token, - uint256 value, - address paymentId - ); - - event Revocation( - bytes32 indexed identifier, - address indexed by, - address indexed token, - uint256 value, - address paymentId - ); - - uint256 ONE_GOLDTOKEN = 1000000000000000000; - address receiver; - uint256 receiverPK; - address sender; - uint256 senderPK; - address trustedIssuer1; - address trustedIssuer2; - - function setUp() public { - address registryAddress = 0x000000000000000000000000000000000000ce10; - - deployCodeTo("Registry.sol", abi.encode(false), registryAddress); - - mockERC20Token = new MockERC20Token(); - escrowContract = new Escrow(true); - escrowContract.initialize(); - registry = Registry(registryAddress); - (receiver, receiverPK) = actorWithPK("receiver"); - (sender, senderPK) = actorWithPK("sender"); - trustedIssuer1 = actor("trustedIssuer1"); - trustedIssuer2 = actor("trustedIssuer2"); - vm.deal(receiver, ONE_GOLDTOKEN); - vm.deal(sender, ONE_GOLDTOKEN); - mockAttestations = new MockAttestations(); - federatedAttestations = new FederatedAttestations(true); - registry.setAddressFor("Attestations", address(mockAttestations)); - registry.setAddressFor("FederatedAttestations", address(federatedAttestations)); - } - - function checkStateAfterDeletingPayment( - address deletedPaymentId, - EscrowedPayment memory payment, - address escrowSender, - bytes32 identifier, - address[] memory expectedSentPaymentIds, - address[] memory expectedReceivedPaymentIds - ) public { - address[] memory sentPaymentIds = escrowContract.getSentPaymentIds(escrowSender); - address[] memory receivedPaymentIds = escrowContract.getReceivedPaymentIds(identifier); - assertEq(sentPaymentIds, expectedSentPaymentIds, "unexpected sentPaymentIds"); - assertEq(receivedPaymentIds, expectedReceivedPaymentIds, "unexpected receivedPaymentIds"); - // Check that indices of last payment structs in previous lists are properly updated - if (expectedSentPaymentIds.length > 0) { - (, , , , uint256 sendersLastPaymentAfterDeleteSentIndex, , , , ) = escrowContract - .escrowedPayments(expectedSentPaymentIds[expectedSentPaymentIds.length - 1]); - - assertEq( - sendersLastPaymentAfterDeleteSentIndex, - payment.sentIndex, - "sentIndex of last payment in sender's sentPaymentIds not updated properly" - ); - } - if (expectedReceivedPaymentIds.length > 0) { - (, , , , , uint256 receiversLastPaymentAfterDeleteReceivedIndex, , , ) = escrowContract - .escrowedPayments(expectedReceivedPaymentIds[expectedReceivedPaymentIds.length - 1]); - assertEq( - receiversLastPaymentAfterDeleteReceivedIndex, - payment.receivedIndex, - "receivedIndex of last payment in receiver's receivedPaymentIds not updated properly" - ); - } - EscrowedPayment memory deletedEscrowedPayment = getEscrowedPayment(deletedPaymentId); - assertEq(deletedEscrowedPayment.value, 0); - - address[] memory trustedIssuersPerPayment = escrowContract.getTrustedIssuersPerPayment( - deletedPaymentId - ); - assertEq(trustedIssuersPerPayment, new address[](0), "trustedIssuersPerPayment not zeroed out"); - } - - function getEscrowedPayment(address paymentId) public view returns (EscrowedPayment memory) { - (bytes32 recipientIdentifier, address _sender, address token, uint256 value, uint256 sentIndex, uint256 receivedIndex, uint256 timestamp, uint256 expirySeconds, uint256 minAttestations) = escrowContract - .escrowedPayments(paymentId); - return - EscrowedPayment( - recipientIdentifier, - _sender, - token, - value, - sentIndex, - receivedIndex, - timestamp, - expirySeconds, - minAttestations - ); - } - - function getParsedSignatureOfAddress(address _address, uint256 privateKey) - public - pure - returns (uint8, bytes32, bytes32) - { - bytes32 addressHash = keccak256(abi.encodePacked(_address)); - bytes32 prefixedHash = ECDSA.toEthSignedMessageHash(addressHash); - return vm.sign(privateKey, prefixedHash); - } - - function mintAndTransfer( - address escrowSender, - bytes32 identifier, - uint256 value, - uint256 expirySeconds, - address paymentId, - uint256 minAttestations, - address[] memory trustedIssuers - ) public { - mockERC20Token.mint(escrowSender, value); - vm.prank(escrowSender); - escrowContract.transferWithTrustedIssuers( - identifier, - address(mockERC20Token), - value, - expirySeconds, - paymentId, - minAttestations, - trustedIssuers - ); - } -} - -contract EscrowInitialize is EscrowTest { - function setUp() public { - super.setUp(); - } - - function test_Should_have_set_the_owner() public { - assertEq(escrowContract.owner(), address(this)); - } - - function testRevertsIf_InitializedAgain() public { - vm.expectRevert("contract already initialized"); - escrowContract.initialize(); - } -} - -contract EscrowAddDefaultTrustedIssuer is EscrowTest { - function setUp() public { - super.setUp(); - } - - function test_AllowOwnerToAddTrustedIssuer() public { - address[] memory expected1 = new address[](0); - assertEq(escrowContract.getDefaultTrustedIssuers(), expected1); - escrowContract.addDefaultTrustedIssuer(trustedIssuer1); - address[] memory expected2 = new address[](1); - expected2[0] = trustedIssuer1; - assertEq(escrowContract.getDefaultTrustedIssuers(), expected2); - } - - function test_RevertsWhenNonOwnerTriesToAdd() public { - vm.expectRevert("Ownable: caller is not the owner"); - vm.prank(sender); - escrowContract.addDefaultTrustedIssuer(trustedIssuer1); - } - - function test_EventEmitted() public { - vm.expectEmit(true, false, false, false); - emit DefaultTrustedIssuerAdded(trustedIssuer1); - escrowContract.addDefaultTrustedIssuer(trustedIssuer1); - } - - function test_RevertsWhenEmptyAddress() public { - vm.expectRevert("trustedIssuer can't be null"); - escrowContract.addDefaultTrustedIssuer(address(0)); - } - - function test_ShouldNotAllowATrustedIssuerToBeAddedTwice() public { - escrowContract.addDefaultTrustedIssuer(trustedIssuer1); - vm.expectRevert("trustedIssuer already in defaultTrustedIssuers"); - escrowContract.addDefaultTrustedIssuer(trustedIssuer1); - } -} - -contract EscrowWhenMaxTrustedIssuersHaveBeenAdded is EscrowTest { - address[] expectedTrustedIssuers; - function setUp() public { - super.setUp(); - - uint256 maxTrustedIssuers = escrowContract.MAX_TRUSTED_ISSUERS_PER_PAYMENT(); - for (uint256 i = 0; i < maxTrustedIssuers; i++) { - address newIssuer = actor(string(abi.encodePacked(i))); - escrowContract.addDefaultTrustedIssuer(newIssuer); - expectedTrustedIssuers.push(newIssuer); - } - } - - function test_SetExpectedDefaultTrustedIssuers() public { - assertEq(escrowContract.getDefaultTrustedIssuers(), expectedTrustedIssuers); - } - - function test_DoesntAllowToAddMoreIssuers() public { - vm.expectRevert("defaultTrustedIssuers.length can't exceed allowed number of trustedIssuers"); - escrowContract.addDefaultTrustedIssuer(trustedIssuer1); - } - - function test_ShouldAllowRemovingAndAddingIssuer() public { - escrowContract.removeDefaultTrustedIssuer( - expectedTrustedIssuers[expectedTrustedIssuers.length - 1], - expectedTrustedIssuers.length - 1 - ); - expectedTrustedIssuers.pop(); - expectedTrustedIssuers.push(trustedIssuer1); - escrowContract.addDefaultTrustedIssuer(trustedIssuer1); - assertEq(escrowContract.getDefaultTrustedIssuers(), expectedTrustedIssuers); - } -} - -contract EscrowRemoveDefaultTrustedIssuer is EscrowTest { - function setUp() public { - super.setUp(); - escrowContract.addDefaultTrustedIssuer(trustedIssuer1); - address[] memory expected2 = new address[](1); - expected2[0] = trustedIssuer1; - assertEq(escrowContract.getDefaultTrustedIssuers(), expected2); - } - - function test_AllowOwnerToRemoveTrustedIssuer() public { - escrowContract.removeDefaultTrustedIssuer(trustedIssuer1, 0); - address[] memory expected1 = new address[](0); - assertEq(escrowContract.getDefaultTrustedIssuers(), expected1); - } - - function test_RevertsWhenNonOwnerTriesToRemoveTrustedIssuer() public { - vm.expectRevert("Ownable: caller is not the owner"); - vm.prank(sender); - escrowContract.removeDefaultTrustedIssuer(trustedIssuer1, 0); - } - - function test_ShouldEmitTheDefaultTrustedIssuerEvent() public { - vm.expectEmit(true, false, false, false); - emit DefaultTrustedIssuerRemoved(trustedIssuer1); - escrowContract.removeDefaultTrustedIssuer(trustedIssuer1, 0); - } - - function test_RevertsWhenIndexIsIncorrect() public { - vm.expectRevert("index is invalid"); - escrowContract.removeDefaultTrustedIssuer(trustedIssuer1, 1); - } - - function test_RevertsWhenIssuerIsNotOnIndex() public { - escrowContract.addDefaultTrustedIssuer(trustedIssuer2); - vm.expectRevert("trustedIssuer does not match address found at defaultTrustedIssuers[index]"); - escrowContract.removeDefaultTrustedIssuer(trustedIssuer1, 1); - } - - function test_AllowOwnerToRemoveTrustedIssuersWhenTwoArePresent() public { - escrowContract.addDefaultTrustedIssuer(trustedIssuer2); - escrowContract.removeDefaultTrustedIssuer(trustedIssuer2, 1); - escrowContract.removeDefaultTrustedIssuer(trustedIssuer1, 0); - address[] memory expected1 = new address[](0); - assertEq(escrowContract.getDefaultTrustedIssuers(), expected1); - } -} - -contract EscrowTestsWithTokens is EscrowTest { - uint256 aValue = 10; - bytes32 aPhoneHash = keccak256("+18005555555"); - uint256 oneDayInSecs = 86400; - - address withdrawKeyAddress = actor("withdrawKeyAddress"); - address anotherWithdrawKeyAddress = actor("anotherWithdrawKeyAddress"); - - function setUp() public { - super.setUp(); - mockERC20Token.mint(sender, aValue); - } - - function transferAndCheckState( - address escrowSender, - bytes32 identifier, - uint256 value, - uint256 expirySeconds, - address paymentId, - uint256 minAttestations, - address[] memory trustedIssuers, - address[] memory expectedSentPaymentIds, - address[] memory expectedReceivedPaymentIds - ) public { - uint256 startingEscrowContractBalance = mockERC20Token.balanceOf(address(escrowContract)); - uint256 startingSenderBalance = mockERC20Token.balanceOf(escrowSender); - - vm.prank(escrowSender); - escrowContract.transferWithTrustedIssuers( - identifier, - address(mockERC20Token), - value, - expirySeconds, - paymentId, - minAttestations, - trustedIssuers - ); - - (, , , uint256 returnedValue, , , , , ) = escrowContract.escrowedPayments(paymentId); - - assertEq(returnedValue, value, "incorrect escrowedPayment.value in payment struct"); - - assertEq( - mockERC20Token.balanceOf(escrowSender), - startingSenderBalance - value, - "incorrect final sender balance" - ); - - assertEq( - mockERC20Token.balanceOf(address(escrowContract)), - startingEscrowContractBalance + value, - "Incorrect final Escrow contract balance" - ); - - address[] memory receivedPaymentIds = escrowContract.getReceivedPaymentIds(identifier); - assertEq(receivedPaymentIds, expectedReceivedPaymentIds); - - address[] memory sentPaymentIds = escrowContract.getSentPaymentIds(escrowSender); - assertEq(sentPaymentIds, expectedSentPaymentIds); - - address[] memory trustedIssuersPerPayment = escrowContract.getTrustedIssuersPerPayment( - paymentId - ); - assertEq(trustedIssuers, trustedIssuersPerPayment); - } - - function test_ShouldAllowUsersToTransferTokensToAnyUser() public { - address[] memory expected = new address[](1); - expected[0] = withdrawKeyAddress; - - transferAndCheckState( - sender, - aPhoneHash, - aValue, - oneDayInSecs, - withdrawKeyAddress, - 0, - new address[](0), - expected, - expected - ); - } - - function test_ShouldAllowTransferWhenMinAttestationsGt0AndIdentifierIsProvided() public { - // should allow transfer when minAttestations > 0 and identifier is provided - address[] memory expected = new address[](1); - expected[0] = withdrawKeyAddress; - - transferAndCheckState( - sender, - aPhoneHash, - aValue, - oneDayInSecs, - withdrawKeyAddress, - 3, - new address[](0), - expected, - expected - ); - } - - function test_ShouldAllowTransferWhenTrustedIssuersAreProvided() public { - // should allow transfer when trustedIssuers are provided - address[] memory expected = new address[](1); - expected[0] = withdrawKeyAddress; - - address[] memory trustedIssuers = new address[](2); - trustedIssuers[0] = trustedIssuer1; - trustedIssuers[1] = trustedIssuer2; - - transferAndCheckState( - sender, - aPhoneHash, - aValue, - oneDayInSecs, - withdrawKeyAddress, - 3, - trustedIssuers, - expected, - expected - ); - } - - function test_ShouldAllowTransferWhenMaxTrustedIssuersAreProvided() public { - // should allow transfer when max trustedIssuers are provided - address[] memory expected = new address[](1); - expected[0] = withdrawKeyAddress; - - uint256 maxTrustedIssuers = escrowContract.MAX_TRUSTED_ISSUERS_PER_PAYMENT(); - - address[] memory trustedIssuers = new address[](maxTrustedIssuers); - for (uint256 i = 0; i < maxTrustedIssuers; i++) { - address newIssuer = actor(string(abi.encodePacked(i))); - trustedIssuers[i] = newIssuer; - } - - transferAndCheckState( - sender, - aPhoneHash, - aValue, - oneDayInSecs, - withdrawKeyAddress, - 3, - trustedIssuers, - expected, - expected - ); - } - - function test_ShouldAllowTransferWhenNoIdentifierIsProvided() public { - // should allow transfer when no identifier is provided - address[] memory expected = new address[](1); - expected[0] = withdrawKeyAddress; - - transferAndCheckState( - sender, - bytes32(0), - aValue, - oneDayInSecs, - withdrawKeyAddress, - 0, - new address[](0), - expected, - expected - ); - } - - function test_ShouldAllowTransferFromSameSenderWithDifferentPaymentIds() public { - // should allow transfers from same sender with different paymentIds - address[] memory expected = new address[](2); - expected[0] = anotherWithdrawKeyAddress; - expected[1] = withdrawKeyAddress; - - mintAndTransfer( - sender, - bytes32(0), - aValue, - oneDayInSecs, - anotherWithdrawKeyAddress, - 0, - new address[](0) - ); - - transferAndCheckState( - sender, - bytes32(0), - aValue, - oneDayInSecs, - withdrawKeyAddress, - 0, - new address[](0), - expected, - expected - ); - } - - function test_ShouldEmitTheTransferEvent() public { - vm.expectEmit(true, true, true, true); - emit Transfer(sender, aPhoneHash, address(mockERC20Token), aValue, withdrawKeyAddress, 2); - - vm.prank(sender); - escrowContract.transferWithTrustedIssuers( - aPhoneHash, - address(mockERC20Token), - aValue, - oneDayInSecs, - withdrawKeyAddress, - 2, - new address[](0) - ); - } - - function test_ShouldEmitTheTrustedIssuerEvent() public { - // should emit the TrustedIssuersSet event - - address[] memory trustedIssuers = new address[](1); - trustedIssuers[0] = trustedIssuer1; - - vm.expectEmit(true, true, true, true); - emit TrustedIssuersSet(withdrawKeyAddress, trustedIssuers); - - vm.prank(sender); - escrowContract.transferWithTrustedIssuers( - aPhoneHash, - address(mockERC20Token), - aValue, - oneDayInSecs, - withdrawKeyAddress, - 2, - trustedIssuers - ); - } - - function test_ShouldNotAllowTwoTransfersWithSamePaymentId() public { - // should not allow two transfers with same paymentId - vm.prank(sender); - escrowContract.transferWithTrustedIssuers( - aPhoneHash, - address(mockERC20Token), - aValue, - oneDayInSecs, - withdrawKeyAddress, - 2, - new address[](0) - ); - - vm.expectRevert("paymentId already used"); - - vm.prank(sender); - escrowContract.transferWithTrustedIssuers( - aPhoneHash, - address(mockERC20Token), - aValue, - oneDayInSecs, - withdrawKeyAddress, - 2, - new address[](0) - ); - } - - function test_ShouldNotAllowTransferWhenTooManyTrustedIssuersAreProvided() public { - // should not allow a transfer when too many trustedIssuers are provided - address[] memory expected = new address[](1); - expected[0] = withdrawKeyAddress; - - uint256 maxTrustedIssuers = escrowContract.MAX_TRUSTED_ISSUERS_PER_PAYMENT(); - - address[] memory trustedIssuers = new address[](maxTrustedIssuers + 1); - for (uint256 i = 0; i < maxTrustedIssuers + 1; i++) { - address newIssuer = actor(string(abi.encodePacked(i))); - trustedIssuers[i] = newIssuer; - } - - vm.expectRevert("Too many trustedIssuers provided"); - - vm.prank(sender); - escrowContract.transferWithTrustedIssuers( - aPhoneHash, - address(mockERC20Token), - aValue, - oneDayInSecs, - withdrawKeyAddress, - 2, - trustedIssuers - ); - } - - function test_ShouldNotAllowTransferWhenTokenIs0() public { - // should not allow a transfer if token is 0 - - vm.expectRevert("Invalid transfer inputs."); - - vm.prank(sender); - escrowContract.transferWithTrustedIssuers( - aPhoneHash, - address(0), - aValue, - oneDayInSecs, - withdrawKeyAddress, - 2, - new address[](0) - ); - } - - function test_ShouldNotAllowTransferIfValueIs0() public { - // should not allow a transfer if value is 0 - - vm.expectRevert("Invalid transfer inputs."); - - vm.prank(sender); - escrowContract.transferWithTrustedIssuers( - aPhoneHash, - address(mockERC20Token), - 0, - oneDayInSecs, - withdrawKeyAddress, - 2, - new address[](0) - ); - } - - function test_ShouldNotAllowTransferIfExpirySecondsIs0() public { - // should not allow a transfer if expirySeconds is 0 - - vm.expectRevert("Invalid transfer inputs."); - - vm.prank(sender); - escrowContract.transferWithTrustedIssuers( - aPhoneHash, - address(mockERC20Token), - aValue, - 0, - withdrawKeyAddress, - 2, - new address[](0) - ); - } - - function test_ShouldNotAllowTransferIfIdentifierIsEmptyButMinAttestationsIsGt0() public { - // should not allow a transfer if identifier is empty but minAttestations is > 0 - - vm.expectRevert("Invalid privacy inputs: Can't require attestations if no identifier"); - - vm.prank(sender); - escrowContract.transferWithTrustedIssuers( - bytes32(0), - address(mockERC20Token), - aValue, - oneDayInSecs, - withdrawKeyAddress, - 1, - new address[](0) - ); - } - - function test_ShouldNotAllowTransferIfIdentifierIsEmptyButTrustedIssuersAreProvided() public { - // should not allow a transfer if identifier is empty but trustedIssuers are provided - - address[] memory trustedIssuers = new address[](1); - trustedIssuers[0] = trustedIssuer1; - - vm.expectRevert("trustedIssuers may only be set when attestations are required"); - - vm.prank(sender); - escrowContract.transferWithTrustedIssuers( - bytes32(0), - address(mockERC20Token), - aValue, - oneDayInSecs, - withdrawKeyAddress, - 0, - trustedIssuers - ); - } - - function test_ShouldNotAllowSettingTrustedIssuersWithoutMinAttestations() public { - // should not allow setting trustedIssuers without minAttestations - - address[] memory trustedIssuers = new address[](1); - trustedIssuers[0] = trustedIssuer1; - - vm.expectRevert("trustedIssuers may only be set when attestations are required"); - - vm.prank(sender); - escrowContract.transferWithTrustedIssuers( - aPhoneHash, - address(mockERC20Token), - aValue, - oneDayInSecs, - withdrawKeyAddress, - 0, - trustedIssuers - ); - } - - function test_ShouldRevertIfTransferValueExceedsBalance() public { - // should revert if transfer value exceeds balance - - address[] memory trustedIssuers = new address[](1); - trustedIssuers[0] = trustedIssuer1; - - vm.expectRevert("SafeERC20: low-level call failed"); - - vm.prank(sender); - escrowContract.transferWithTrustedIssuers( - aPhoneHash, - address(mockERC20Token), - aValue + 1, - oneDayInSecs, - withdrawKeyAddress, - 2, - new address[](0) - ); - } - - function test_Transfer_WhenNoDefaultTrustedIssuersAreSet_ShouldSetThemToEmptyList() public { - // when no defaut trustedIssuers are set; should set trustedIssuersPerPaymentId to empty list - vm.prank(sender); - escrowContract.transfer( - aPhoneHash, - address(mockERC20Token), - aValue, - oneDayInSecs, - withdrawKeyAddress, - 2 - ); - - address[] memory expected = new address[](0); - address[] memory trustedIssuersPerPayment = escrowContract.getTrustedIssuersPerPayment( - withdrawKeyAddress - ); - assertEq(trustedIssuersPerPayment, expected); - } - - function test_Transfer_WhenDefaultTrustedIssuersAreSet_ShouldSetTrustedIssuersPerPaymentIdToDefaultWhenMinAttestationsGt0() - public - { - // when defaut trustedIssuers are set; should set trustedIssuersPerPaymentId to default when minAttestations>0 - - escrowContract.addDefaultTrustedIssuer(trustedIssuer1); - escrowContract.addDefaultTrustedIssuer(trustedIssuer2); - - address[] memory trustedIssuers = new address[](2); - trustedIssuers[0] = trustedIssuer1; - trustedIssuers[1] = trustedIssuer2; - - vm.prank(sender); - escrowContract.transfer( - aPhoneHash, - address(mockERC20Token), - aValue, - oneDayInSecs, - withdrawKeyAddress, - 2 - ); - - address[] memory trustedIssuersPerPayment = escrowContract.getTrustedIssuersPerPayment( - withdrawKeyAddress - ); - assertEq(trustedIssuersPerPayment, trustedIssuers); - } - - function test_Transfer_WhenDefaultTrustedIssuersAreSet_ShouldSetTrustedIssuersPerPaymentIdToEmptyListWhenMinAttestationsEq0() - public - { - // when defaut trustedIssuers are set; should set trustedIssuersPerPaymentId to empty list when minAttestations==0 - - escrowContract.addDefaultTrustedIssuer(trustedIssuer1); - escrowContract.addDefaultTrustedIssuer(trustedIssuer2); - - vm.prank(sender); - escrowContract.transfer( - aPhoneHash, - address(mockERC20Token), - aValue, - oneDayInSecs, - withdrawKeyAddress, - 0 - ); - - address[] memory trustedIssuersPerPayment = escrowContract.getTrustedIssuersPerPayment( - withdrawKeyAddress - ); - address[] memory expected = new address[](0); - assertEq(trustedIssuersPerPayment, expected); - } -} - -contract EscrowWithdrawalTest is EscrowTest { - uint256 aValue = 10; - bytes32 aPhoneHash = keccak256("+18005555555"); - uint256 oneDayInSecs = 86400; - - address withdrawKeyAddress; - uint256 withdrawalKeyAddressPK; - address anotherWithdrawKeyAddress; - uint256 anotherWithdrawKeyAddressPK; - - address uniquePaymentIDWithdraw; - uint256 uniquePaymentIDWithdrawPK; - - function setUp() public { - (withdrawKeyAddress, withdrawalKeyAddressPK) = actorWithPK("withdrawKeyAddress"); - (anotherWithdrawKeyAddress, anotherWithdrawKeyAddressPK) = actorWithPK( - "anotherWithdrawKeyAddress" - ); - - uniquePaymentIDWithdraw = withdrawKeyAddress; - uniquePaymentIDWithdrawPK = withdrawalKeyAddressPK; - - super.setUp(); - mockERC20Token.mint(sender, aValue); - } - - function completeAttestations(address account, bytes32 identifier, uint256 attestationsToComplete) - public - { - for (uint256 i = 0; i < attestationsToComplete; i++) { - vm.prank(account); - mockAttestations.complete(identifier, 0, bytes32(0), bytes32(0)); - } - } - - function withdrawAndCheckState( - address escrowSender, - address escrowReceiver, - bytes32 identifier, - address paymentId, - address[] memory expectedSentPaymentIds, - address[] memory expectedReceivedPaymentIds - ) public { - uint256 receiverBalanceBefore = mockERC20Token.balanceOf(escrowReceiver); - uint256 escrowContractBalanceBefore = mockERC20Token.balanceOf(address(escrowContract)); - - EscrowedPayment memory payment = getEscrowedPayment(paymentId); - - (uint8 v, bytes32 r, bytes32 s) = getParsedSignatureOfAddress( - escrowReceiver, - uniquePaymentIDWithdrawPK - ); - vm.prank(escrowReceiver); - escrowContract.withdraw(paymentId, v, r, s); - - assertEq( - mockERC20Token.balanceOf(escrowReceiver), - receiverBalanceBefore + payment.value, - "incorrect final receiver balance" - ); - assertEq( - mockERC20Token.balanceOf(address(escrowContract)), - escrowContractBalanceBefore - payment.value, - "incorrect final Escrow contract balance" - ); - checkStateAfterDeletingPayment( - paymentId, - payment, - escrowSender, - identifier, - expectedSentPaymentIds, - expectedReceivedPaymentIds - ); - } - - function test_ShouldFailIfPaymentIdDoesNotExist() public { - // should fail when no payment has been escrowed - (uint8 v, bytes32 r, bytes32 s) = getParsedSignatureOfAddress( - receiver, - uniquePaymentIDWithdrawPK - ); - vm.expectRevert("Invalid withdraw value."); - vm.prank(receiver); - escrowContract.withdraw(uniquePaymentIDWithdraw, v, r, s); - } - - function test_ShouldAllowWithdrawalWithPossesionOfPKAndNoAttestations() public { - // should allow withdrawal with possession of PK and no attestations - mintAndTransfer( - sender, - bytes32(0), - aValue, - oneDayInSecs, - uniquePaymentIDWithdraw, - 0, - new address[](0) - ); - - withdrawAndCheckState( - sender, - receiver, - bytes32(0), - uniquePaymentIDWithdraw, - new address[](0), - new address[](0) - ); - } - - function test_ShouldEmitTheTrustedIssuersUnsetEvent() public { - // should emit the TrustedIssuersUnset event - mintAndTransfer( - sender, - bytes32(0), - aValue, - oneDayInSecs, - uniquePaymentIDWithdraw, - 0, - new address[](0) - ); - - vm.expectEmit(true, true, true, true); - emit TrustedIssuersUnset(uniquePaymentIDWithdraw); - - withdrawAndCheckState( - sender, - receiver, - bytes32(0), - uniquePaymentIDWithdraw, - new address[](0), - new address[](0) - ); - } - - function test_ShouldEmitWithdwaralEvent() public { - // should emit the Withdrawal event - mintAndTransfer( - sender, - bytes32(0), - aValue, - oneDayInSecs, - uniquePaymentIDWithdraw, - 0, - new address[](0) - ); - - vm.expectEmit(true, true, true, true); - emit Withdrawal(bytes32(0), receiver, address(mockERC20Token), aValue, uniquePaymentIDWithdraw); - - withdrawAndCheckState( - sender, - receiver, - bytes32(0), - uniquePaymentIDWithdraw, - new address[](0), - new address[](0) - ); - } - - function test_ShouldWithdrawProperlyWhenSecondPaymentEscrowedWithEmptyIdentifier() public { - // should withdraw properly when second payment escrowed with empty identifier - - address[] memory expected = new address[](1); - expected[0] = anotherWithdrawKeyAddress; - - mintAndTransfer( - sender, - bytes32(0), - aValue, - oneDayInSecs, - uniquePaymentIDWithdraw, - 0, - new address[](0) - ); - mintAndTransfer( - sender, - bytes32(0), - aValue, - oneDayInSecs, - anotherWithdrawKeyAddress, - 0, - new address[](0) - ); - - withdrawAndCheckState( - sender, - receiver, - bytes32(0), - uniquePaymentIDWithdraw, - expected, - expected - ); - } - - function test_ShouldWithdawProperlyWhenSenderSecondPaymentHasAnIdentifierWithAttestations() - public - { - // should withdraw properly when sender's second payment has an identifier with attestations - - address[] memory expected = new address[](1); - expected[0] = anotherWithdrawKeyAddress; - - mintAndTransfer( - sender, - bytes32(0), - aValue, - oneDayInSecs, - uniquePaymentIDWithdraw, - 0, - new address[](0) - ); - mintAndTransfer( - sender, - aPhoneHash, - aValue, - oneDayInSecs, - anotherWithdrawKeyAddress, - 3, - new address[](0) - ); - - withdrawAndCheckState( - sender, - receiver, - bytes32(0), - uniquePaymentIDWithdraw, - expected, - new address[](0) - ); - } - - function test_ShouldNotAllowWithdrawingWithoutAValidSignatureUsingTheWithdrawalKey() public { - // should not allow withdrawing without a valid signature using the withdraw key - - address[] memory expected = new address[](1); - expected[0] = anotherWithdrawKeyAddress; - - mintAndTransfer( - sender, - bytes32(0), - aValue, - oneDayInSecs, - uniquePaymentIDWithdraw, - 0, - new address[](0) - ); - - (uint8 v, bytes32 r, bytes32 s) = getParsedSignatureOfAddress( - receiver, - uniquePaymentIDWithdrawPK - ); - vm.expectRevert("Failed to prove ownership of the withdraw key"); - // The signature is invalidated if it's sent from a different address - vm.prank(address(this)); - escrowContract.withdraw(uniquePaymentIDWithdraw, v, r, s); - } - - function test_WhenFirstPaymentWithIdentifierAndMinAttestations_ShouldAllowToWithdraw() public { - // when first payment is escrowed by a sender for identifier && minAttestations; should allow users to withdraw after completing attestations - uint256 minAttestations = 3; - - mintAndTransfer( - sender, - aPhoneHash, - aValue, - oneDayInSecs, - uniquePaymentIDWithdraw, - minAttestations, - new address[](0) - ); - - completeAttestations(receiver, aPhoneHash, minAttestations); - withdrawAndCheckState( - sender, - receiver, - aPhoneHash, - uniquePaymentIDWithdraw, - new address[](0), - new address[](0) - ); - } - - function test_WhenFirstPaymentWithIdentifierAndMinAttestations_ShouldNotAllowToWithdrawWhenLessThanMinAttestations() - public - { - // should not allow a user to withdraw a payment if they have fewer than minAttestations - uint256 minAttestations = 3; - - mintAndTransfer( - sender, - aPhoneHash, - aValue, - oneDayInSecs, - uniquePaymentIDWithdraw, - minAttestations, - new address[](0) - ); - - completeAttestations(receiver, aPhoneHash, minAttestations - 1); - vm.expectRevert( - "This account does not have the required attestations to withdraw this payment." - ); - (uint8 v, bytes32 r, bytes32 s) = getParsedSignatureOfAddress( - receiver, - uniquePaymentIDWithdrawPK - ); - vm.prank(receiver); - escrowContract.withdraw(uniquePaymentIDWithdraw, v, r, s); - } - - function test_ShouldWithdawProperlyWhenSenderSecondPaymentHasAnIdentifier() public { - // should withdraw properly when sender's second payment has an identifier - uint256 minAttestations = 3; - - address[] memory expected = new address[](1); - expected[0] = anotherWithdrawKeyAddress; - - mintAndTransfer( - sender, - aPhoneHash, - aValue, - oneDayInSecs, - uniquePaymentIDWithdraw, - minAttestations, - new address[](0) - ); - mintAndTransfer( - sender, - aPhoneHash, - aValue, - oneDayInSecs, - anotherWithdrawKeyAddress, - 0, - new address[](0) - ); - - completeAttestations(receiver, aPhoneHash, minAttestations); - withdrawAndCheckState( - sender, - receiver, - bytes32(0), - uniquePaymentIDWithdraw, - expected, - new address[](0) - ); - } - - function test_WhenTrustedIssuersAreSetForPayment_AttestationsSolIsTrustedIssuer_ShouldAllowTransferWhenCompletingAttestations() - public - { - uint256 minAttestations = 3; - - address[] memory trustedIssuers = new address[](3); - trustedIssuers[0] = trustedIssuer1; - trustedIssuers[1] = trustedIssuer2; - trustedIssuers[2] = address(mockAttestations); - - mintAndTransfer( - sender, - aPhoneHash, - aValue, - oneDayInSecs, - uniquePaymentIDWithdraw, - minAttestations, - trustedIssuers - ); - - completeAttestations(receiver, aPhoneHash, minAttestations); - withdrawAndCheckState( - sender, - receiver, - aPhoneHash, - uniquePaymentIDWithdraw, - new address[](0), - new address[](0) - ); - } - - function test_WhenTrustedIssuersAreSetForPayment_AttestationsSolIsTrustedIssuer_ShouldNotAllowWithdrawalIfNoAttestationsInFederatedAttestations() - public - { - uint256 minAttestations = 3; - - address[] memory trustedIssuers = new address[](3); - trustedIssuers[0] = trustedIssuer1; - trustedIssuers[1] = trustedIssuer2; - trustedIssuers[2] = address(mockAttestations); - - mintAndTransfer( - sender, - aPhoneHash, - aValue, - oneDayInSecs, - uniquePaymentIDWithdraw, - minAttestations, - trustedIssuers - ); - - completeAttestations(receiver, aPhoneHash, minAttestations - 1); - vm.expectRevert( - "This account does not have the required attestations to withdraw this payment." - ); - (uint8 v, bytes32 r, bytes32 s) = getParsedSignatureOfAddress( - receiver, - uniquePaymentIDWithdrawPK - ); - vm.prank(receiver); - escrowContract.withdraw(uniquePaymentIDWithdraw, v, r, s); - } - - function test_WhenTrustedIssuersAreSetForPayment_AttestationsSolIsTrustedIssuer_ShouldAllowWithdrawalIfAttestationInFederatedAttestations() - public - { - uint256 minAttestations = 3; - - address[] memory trustedIssuers = new address[](3); - trustedIssuers[0] = trustedIssuer1; - trustedIssuers[1] = trustedIssuer2; - trustedIssuers[2] = address(mockAttestations); - - mintAndTransfer( - sender, - aPhoneHash, - aValue, - oneDayInSecs, - uniquePaymentIDWithdraw, - minAttestations, - trustedIssuers - ); - - completeAttestations(receiver, aPhoneHash, minAttestations - 1); - vm.prank(trustedIssuer2); - federatedAttestations.registerAttestationAsIssuer(aPhoneHash, receiver, 0); - withdrawAndCheckState( - sender, - receiver, - aPhoneHash, - uniquePaymentIDWithdraw, - new address[](0), - new address[](0) - ); - } - - function test_WhenTrustedIssuersAreSetForPayment_AttestationsSolNotInTrustedIssuer_ShouldNotAllowWithdrawalIfNoAttestationsInFederatedAttestations() - public - { - uint256 minAttestations = 2; - - address[] memory trustedIssuers = new address[](2); - trustedIssuers[0] = trustedIssuer1; - trustedIssuers[1] = trustedIssuer2; - - mintAndTransfer( - sender, - aPhoneHash, - aValue, - oneDayInSecs, - uniquePaymentIDWithdraw, - minAttestations, - trustedIssuers - ); - - completeAttestations(receiver, aPhoneHash, minAttestations - 1); - vm.expectRevert( - "This account does not have the required attestations to withdraw this payment." - ); - (uint8 v, bytes32 r, bytes32 s) = getParsedSignatureOfAddress( - receiver, - uniquePaymentIDWithdrawPK - ); - vm.prank(receiver); - escrowContract.withdraw(uniquePaymentIDWithdraw, v, r, s); - } - - function test_WhenTrustedIssuersAreSetForPayment_AttestationsSolNotInTrustedIssuer_ShouldAllowWithdrawalIfAttestationInFederatedAttestations() - public - { - uint256 minAttestations = 2; - - address[] memory trustedIssuers = new address[](2); - trustedIssuers[0] = trustedIssuer1; - trustedIssuers[1] = trustedIssuer2; - - mintAndTransfer( - sender, - aPhoneHash, - aValue, - oneDayInSecs, - uniquePaymentIDWithdraw, - minAttestations, - trustedIssuers - ); - - completeAttestations(receiver, aPhoneHash, minAttestations - 1); - vm.prank(trustedIssuer2); - federatedAttestations.registerAttestationAsIssuer(aPhoneHash, receiver, 0); - withdrawAndCheckState( - sender, - receiver, - aPhoneHash, - uniquePaymentIDWithdraw, - new address[](0), - new address[](0) - ); - } -} - -contract EscrowRevokeTestIdentifierEmptyMinAttestations0TrustedIssuersEmpty is EscrowTest { - uint256 aValue = 10; - bytes32 aPhoneHash = keccak256("+18005555555"); - uint256 oneDayInSecs = 86400; - - address withdrawKeyAddress; - uint256 withdrawalKeyAddressPK; - address anotherWithdrawKeyAddress; - uint256 anotherWithdrawKeyAddressPK; - - address uniquePaymentIDRevoke; - - bytes32 identifier; - uint256 minAttestations; - address[] trustedIssuers; - - uint8 v; - bytes32 r; - bytes32 s; - - function setUp() public { - (withdrawKeyAddress, withdrawalKeyAddressPK) = actorWithPK("withdrawKeyAddress"); - (anotherWithdrawKeyAddress, anotherWithdrawKeyAddressPK) = actorWithPK( - "anotherWithdrawKeyAddress" - ); - - super.setUp(); - mockERC20Token.mint(sender, aValue); - - identifier = bytes32(0); - minAttestations = 0; - trustedIssuers = new address[](0); - - mintAndTransfer( - sender, - identifier, - aValue, - oneDayInSecs, - withdrawKeyAddress, - minAttestations, - trustedIssuers - ); - - mintAndTransfer( - sender, - identifier, - aValue, - oneDayInSecs, - anotherWithdrawKeyAddress, - minAttestations, - trustedIssuers - ); - uniquePaymentIDRevoke = withdrawKeyAddress; - (v, r, s) = getParsedSignatureOfAddress(receiver, withdrawalKeyAddressPK); - - if (trustedIssuers.length > 0) { - vm.prank(trustedIssuers[0]); - federatedAttestations.registerAttestationAsIssuer(identifier, receiver, 0); - } - } - - function test_ShouldAllowSenderToRedeemPaymentAfterPaymentHasExpired() public { - // should allow sender to redeem payment after payment has expired - vm.warp(oneDayInSecs + 1); - - address[] memory expected = new address[](1); - expected[0] = anotherWithdrawKeyAddress; - - uint256 senderBalanceBefore = mockERC20Token.balanceOf(sender); - uint256 escrowContractBalanceBefore = mockERC20Token.balanceOf(address(escrowContract)); - EscrowedPayment memory paymentBefore = getEscrowedPayment(uniquePaymentIDRevoke); - - vm.prank(sender); - escrowContract.revoke(uniquePaymentIDRevoke); - - assertEq( - mockERC20Token.balanceOf(sender), - senderBalanceBefore + aValue, - "incorrect final sender balance" - ); - - assertEq( - mockERC20Token.balanceOf(address(escrowContract)), - escrowContractBalanceBefore - aValue, - "incorrect final Escrow contract balance" - ); - - checkStateAfterDeletingPayment( - uniquePaymentIDRevoke, - paymentBefore, - sender, - identifier, - expected, - expected - ); - } - - function test_ShouldEmitTheTrustedIssuersUnsetEvent() public { - // should emit the TrustedIssuersUnset event - vm.warp(oneDayInSecs + 1); - - vm.expectEmit(true, true, true, true); - emit TrustedIssuersUnset(uniquePaymentIDRevoke); - - vm.prank(sender); - escrowContract.revoke(uniquePaymentIDRevoke); - } - - function test_ShouldEmitRevokationEvent() public { - // should emit the Revocation event - vm.warp(oneDayInSecs + 1); - - vm.expectEmit(true, true, true, true); - emit Revocation(identifier, sender, address(mockERC20Token), aValue, uniquePaymentIDRevoke); - - vm.prank(sender); - escrowContract.revoke(uniquePaymentIDRevoke); - } - - function test_ShouldNotAllowSenderToRevokeAfterReceiverWithdraws() public { - // should not allow sender to revoke after receiver withdraws - vm.prank(receiver); - escrowContract.withdraw(uniquePaymentIDRevoke, v, r, s); - vm.expectRevert("Only sender of payment can attempt to revoke payment."); - vm.prank(sender); - escrowContract.revoke(uniquePaymentIDRevoke); - } - - function test_ShouldNotAllowReceiverToRedeemPAymentAfterSenderRevokesIt() public { - // should not allow receiver to redeem payment after sender revokes it - vm.warp(oneDayInSecs + 1); - vm.prank(sender); - escrowContract.revoke(uniquePaymentIDRevoke); - vm.expectRevert("Invalid withdraw value."); - vm.prank(receiver); - escrowContract.withdraw(uniquePaymentIDRevoke, v, r, s); - } - - function test_ShouldNotAllowSenderToRevokePaymentBeforePaymentHasExpired() public { - // should not allow sender to revoke payment before payment has expired - vm.expectRevert("Transaction not redeemable for sender yet."); - vm.prank(sender); - escrowContract.revoke(uniquePaymentIDRevoke); - } - - function test_ShouldNotAllowReceiverToUseRevokeFunction() public { - // should not allow receiver to use revoke function - vm.expectRevert("Only sender of payment can attempt to revoke payment."); - vm.prank(receiver); - escrowContract.revoke(uniquePaymentIDRevoke); - } -} - -contract EscrowRevokeTestIdentifierNotEmptyMinAttestations0TrustedIssuersEmpty is EscrowTest { - uint256 aValue = 10; - bytes32 aPhoneHash = keccak256("+18005555555"); - uint256 oneDayInSecs = 86400; - - address withdrawKeyAddress; - uint256 withdrawalKeyAddressPK; - address anotherWithdrawKeyAddress; - uint256 anotherWithdrawKeyAddressPK; - - address uniquePaymentIDRevoke; - - bytes32 identifier; - uint256 minAttestations; - address[] trustedIssuers; - - uint8 v; - bytes32 r; - bytes32 s; - - function setUp() public { - (withdrawKeyAddress, withdrawalKeyAddressPK) = actorWithPK("withdrawKeyAddress"); - (anotherWithdrawKeyAddress, anotherWithdrawKeyAddressPK) = actorWithPK( - "anotherWithdrawKeyAddress" - ); - - super.setUp(); - mockERC20Token.mint(sender, aValue); - - identifier = aPhoneHash; - minAttestations = 0; - trustedIssuers = new address[](0); - - mintAndTransfer( - sender, - identifier, - aValue, - oneDayInSecs, - withdrawKeyAddress, - minAttestations, - trustedIssuers - ); - - mintAndTransfer( - sender, - identifier, - aValue, - oneDayInSecs, - anotherWithdrawKeyAddress, - minAttestations, - trustedIssuers - ); - uniquePaymentIDRevoke = withdrawKeyAddress; - (v, r, s) = getParsedSignatureOfAddress(receiver, withdrawalKeyAddressPK); - - if (trustedIssuers.length > 0) { - vm.prank(trustedIssuers[0]); - federatedAttestations.registerAttestationAsIssuer(identifier, receiver, 0); - } - } - - function test_ShouldAllowSenderToRedeemPaymentAfterPaymentHasExpired() public { - // should allow sender to redeem payment after payment has expired - vm.warp(oneDayInSecs + 1); - - address[] memory expected = new address[](1); - expected[0] = anotherWithdrawKeyAddress; - - uint256 senderBalanceBefore = mockERC20Token.balanceOf(sender); - uint256 escrowContractBalanceBefore = mockERC20Token.balanceOf(address(escrowContract)); - EscrowedPayment memory paymentBefore = getEscrowedPayment(uniquePaymentIDRevoke); - - vm.prank(sender); - escrowContract.revoke(uniquePaymentIDRevoke); - - assertEq( - mockERC20Token.balanceOf(sender), - senderBalanceBefore + aValue, - "incorrect final sender balance" - ); - - assertEq( - mockERC20Token.balanceOf(address(escrowContract)), - escrowContractBalanceBefore - aValue, - "incorrect final Escrow contract balance" - ); - - checkStateAfterDeletingPayment( - uniquePaymentIDRevoke, - paymentBefore, - sender, - identifier, - expected, - expected - ); - } - - function test_ShouldEmitTheTrustedIssuersUnsetEvent() public { - // should emit the TrustedIssuersUnset event - vm.warp(oneDayInSecs + 1); - - vm.expectEmit(true, true, true, true); - emit TrustedIssuersUnset(uniquePaymentIDRevoke); - - vm.prank(sender); - escrowContract.revoke(uniquePaymentIDRevoke); - } - - function test_ShouldEmitRevokationEvent() public { - // should emit the Revocation event - vm.warp(oneDayInSecs + 1); - - vm.expectEmit(true, true, true, true); - emit Revocation(identifier, sender, address(mockERC20Token), aValue, uniquePaymentIDRevoke); - - vm.prank(sender); - escrowContract.revoke(uniquePaymentIDRevoke); - } - - function test_ShouldNotAllowSenderToRevokeAfterReceiverWithdraws() public { - // should not allow sender to revoke after receiver withdraws - vm.prank(receiver); - escrowContract.withdraw(uniquePaymentIDRevoke, v, r, s); - vm.expectRevert("Only sender of payment can attempt to revoke payment."); - vm.prank(sender); - escrowContract.revoke(uniquePaymentIDRevoke); - } - - function test_ShouldNotAllowReceiverToRedeemPAymentAfterSenderRevokesIt() public { - // should not allow receiver to redeem payment after sender revokes it - vm.warp(oneDayInSecs + 1); - vm.prank(sender); - escrowContract.revoke(uniquePaymentIDRevoke); - vm.expectRevert("Invalid withdraw value."); - vm.prank(receiver); - escrowContract.withdraw(uniquePaymentIDRevoke, v, r, s); - } - - function test_ShouldNotAllowSenderToRevokePaymentBeforePaymentHasExpired() public { - // should not allow sender to revoke payment before payment has expired - vm.expectRevert("Transaction not redeemable for sender yet."); - vm.prank(sender); - escrowContract.revoke(uniquePaymentIDRevoke); - } - - function test_ShouldNotAllowReceiveToUseRevokeFunction() public { - // should not allow receiver to use revoke function - vm.expectRevert("Only sender of payment can attempt to revoke payment."); - vm.prank(receiver); - escrowContract.revoke(uniquePaymentIDRevoke); - } -} - -contract EscrowRevokeTestIdentifierNotEmptyMinAttestations1TrustedIssuersNonEmpty is EscrowTest { - uint256 aValue = 10; - bytes32 aPhoneHash = keccak256("+18005555555"); - uint256 oneDayInSecs = 86400; - - address withdrawKeyAddress; - uint256 withdrawalKeyAddressPK; - address anotherWithdrawKeyAddress; - uint256 anotherWithdrawKeyAddressPK; - - address uniquePaymentIDRevoke; - - bytes32 identifier; - uint256 minAttestations; - address[] trustedIssuers; - - uint8 v; - bytes32 r; - bytes32 s; - - function setUp() public { - (withdrawKeyAddress, withdrawalKeyAddressPK) = actorWithPK("withdrawKeyAddress"); - (anotherWithdrawKeyAddress, anotherWithdrawKeyAddressPK) = actorWithPK( - "anotherWithdrawKeyAddress" - ); - - super.setUp(); - mockERC20Token.mint(sender, aValue); - - identifier = aPhoneHash; - minAttestations = 1; - trustedIssuers = new address[](2); - trustedIssuers[0] = trustedIssuer1; - trustedIssuers[1] = trustedIssuer2; - - mintAndTransfer( - sender, - identifier, - aValue, - oneDayInSecs, - withdrawKeyAddress, - minAttestations, - trustedIssuers - ); - - mintAndTransfer( - sender, - identifier, - aValue, - oneDayInSecs, - anotherWithdrawKeyAddress, - minAttestations, - trustedIssuers - ); - uniquePaymentIDRevoke = withdrawKeyAddress; - (v, r, s) = getParsedSignatureOfAddress(receiver, withdrawalKeyAddressPK); - - if (trustedIssuers.length > 0) { - vm.prank(trustedIssuers[0]); - federatedAttestations.registerAttestationAsIssuer(identifier, receiver, 0); - } - } - - function test_ShouldAllowSenderToRedeemPaymentAfterPaymentHasExpired() public { - // should allow sender to redeem payment after payment has expired - vm.warp(oneDayInSecs + 1); - - address[] memory expected = new address[](1); - expected[0] = anotherWithdrawKeyAddress; - - uint256 senderBalanceBefore = mockERC20Token.balanceOf(sender); - uint256 escrowContractBalanceBefore = mockERC20Token.balanceOf(address(escrowContract)); - EscrowedPayment memory paymentBefore = getEscrowedPayment(uniquePaymentIDRevoke); - - vm.prank(sender); - escrowContract.revoke(uniquePaymentIDRevoke); - - assertEq( - mockERC20Token.balanceOf(sender), - senderBalanceBefore + aValue, - "incorrect final sender balance" - ); - - assertEq( - mockERC20Token.balanceOf(address(escrowContract)), - escrowContractBalanceBefore - aValue, - "incorrect final Escrow contract balance" - ); - - checkStateAfterDeletingPayment( - uniquePaymentIDRevoke, - paymentBefore, - sender, - identifier, - expected, - expected - ); - } - - function test_ShouldEmitTheTrustedIssuersUnsetEvent() public { - // should emit the TrustedIssuersUnset event - vm.warp(oneDayInSecs + 1); - - vm.expectEmit(true, true, true, true); - emit TrustedIssuersUnset(uniquePaymentIDRevoke); - - vm.prank(sender); - escrowContract.revoke(uniquePaymentIDRevoke); - } - - function test_ShouldEmitRevokationEvent() public { - // should emit the Revocation event - vm.warp(oneDayInSecs + 1); - - vm.expectEmit(true, true, true, true); - emit Revocation(identifier, sender, address(mockERC20Token), aValue, uniquePaymentIDRevoke); - - vm.prank(sender); - escrowContract.revoke(uniquePaymentIDRevoke); - } - - function test_ShouldNotAllowSenderToRevokeAfterReceiverWithdraws() public { - // should not allow sender to revoke after receiver withdraws - vm.prank(receiver); - escrowContract.withdraw(uniquePaymentIDRevoke, v, r, s); - vm.expectRevert("Only sender of payment can attempt to revoke payment."); - vm.prank(sender); - escrowContract.revoke(uniquePaymentIDRevoke); - } - - function test_ShouldNotAllowReceiverToRedeemPAymentAfterSenderRevokesIt() public { - // should not allow receiver to redeem payment after sender revokes it - vm.warp(oneDayInSecs + 1); - vm.prank(sender); - escrowContract.revoke(uniquePaymentIDRevoke); - vm.expectRevert("Invalid withdraw value."); - vm.prank(receiver); - escrowContract.withdraw(uniquePaymentIDRevoke, v, r, s); - } - - function test_ShouldNotAllowSenderToRevokePaymentBeforePaymentHasExpired() public { - // should not allow sender to revoke payment before payment has expired - vm.expectRevert("Transaction not redeemable for sender yet."); - vm.prank(sender); - escrowContract.revoke(uniquePaymentIDRevoke); - } - - function test_ShouldNotAllowReceiveToUseRevokeFunction() public { - // should not allow receiver to use revoke function - vm.expectRevert("Only sender of payment can attempt to revoke payment."); - vm.prank(receiver); - escrowContract.revoke(uniquePaymentIDRevoke); - } -} diff --git a/packages/protocol/test-sol/identity/FederatedAttestations.t.sol b/packages/protocol/test-sol/identity/FederatedAttestations.t.sol deleted file mode 100644 index 3a27f0404..000000000 --- a/packages/protocol/test-sol/identity/FederatedAttestations.t.sol +++ /dev/null @@ -1,1871 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.5.13; -pragma experimental ABIEncoderV2; - -import "celo-foundry/Test.sol"; -import "@celo-contracts/identity/test/AttestationsTest.sol"; -import "@celo-contracts/identity/FederatedAttestations.sol"; -import "@celo-contracts/identity/test/MockERC20Token.sol"; -import "@celo-contracts/identity/test/MockRandom.sol"; -import "@celo-contracts/governance/test/MockElection.sol"; -import "@celo-contracts/governance/test/MockLockedGold.sol"; -import "@celo-contracts/governance/test/MockValidators.sol"; -import "@celo-contracts/common/Registry.sol"; -import "@celo-contracts/common/Accounts.sol"; - -contract FederatedAttestationsFoundryTest is Test { - enum KeyOffsets { - NO_OFFSET, - VALIDATING_KEY_OFFSET, - ATTESTING_KEY_OFFSET, - NEW_VALIDATING_KEY_OFFSET, - VOTING_KEY_OFFSET - } - - AttestationsTest attestationsTest; - MockERC20Token mockERC20Token; - MockERC20Token otherMockERC20Token; - MockElection mockElection; - MockLockedGold mockLockedGold; - MockValidators mockValidators; - MockRandom random; - Registry registry; - Accounts accounts; - FederatedAttestations federatedAttestations; - - address caller; - uint256 callerPK; - address caller2; - uint256 callerPK2; - address caller3; - uint256 callerPK3; - address caller4; - uint256 callerPK4; - address caller5; - uint256 callerPK5; - address caller6; - uint256 callerPK6; - address caller7; - uint256 callerPK7; - address caller8; - uint256 callerPK8; - address nonIssuer = actor("nonIssuer"); - string phoneNumber = "+18005551212"; - bytes32 phoneHash; - string phoneNumber2 = "+18005551213"; - bytes32 phoneHash2; - - uint256 attestationsRequested = 3; - uint256 attestationExpiryBlocks = (60 * 60) / 5; - uint256 selectIssuersWaitBlocks = 4; - uint256 maxAttestations = 20; - uint256 attestationFee = 0.5 ether; - - uint256 chainId = 31337; - bytes32 constant AttestationSignerRole = keccak256(abi.encodePacked("celo.org/core/attestation")); - bytes32 constant RandomRole = keccak256(abi.encodePacked("random")); - - address account1; - address signer1; - address issuer1; - address account2; - address issuer2; - address issuer2Singer; - address issuer2Singer2; - address issuer3; - - mapping(address => uint256) public privateKeys; - - event EIP712DomainSeparatorSet(bytes32 eip712DomainSeparator); - event AttestationRegistered( - bytes32 indexed identifier, - address indexed issuer, - address indexed account, - address signer, - uint64 issuedOn, - uint64 publishedOn - ); - event AttestationRevoked( - bytes32 indexed identifier, - address indexed issuer, - address indexed account, - address signer, - uint64 issuedOn, - uint64 publishedOn - ); - - bytes32 constant EIP712DOMAIN_TYPEHASH = keccak256( - "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" - ); - - bytes32 public constant EIP712_OWNERSHIP_ATTESTATION_TYPEHASH = keccak256( - abi.encodePacked( - "OwnershipAttestation(bytes32 identifier,address issuer,", - "address account,address signer,uint64 issuedOn)" - ) - ); - - struct Domain { - string name; - string version; - uint256 chainId; - address verifyingContract; - } - - struct OwnershipAttestations { - bytes32 identifier; - address issuer; - address account; - address signer; - uint64 issuedOn; - } - - struct AttestationTestCase { - address account; - address signer; - uint256 issuedOn; - } - - struct IdentifierTestCase { - bytes32 identifier; - address signer; - } - - function getSignatureForAttestation( - bytes32 identifier, - address issuer, - address account, - uint256 issuedOn, - uint256 privateKeySigner, // This is used to simulate signing in the test environment - uint256 _chainId, - address verifyingContract - ) public pure returns (uint8 v, bytes32 r, bytes32 s) { - bytes32 dataHash = generateTypedDataHash( - Domain("FederatedAttestations", "1.0", _chainId, verifyingContract), - OwnershipAttestations( - identifier, - issuer, - account, - getAddressFromPrivateKey(privateKeySigner), - uint64(issuedOn) - ) - ); - - // Simulate the signing of the digest with the provided private key using the EVM function - (v, r, s) = vm.sign(privateKeySigner, dataHash); - - // Return the signature components - return (v, r, s); - } - - function generateTypedDataHash( - Domain memory domain, - OwnershipAttestations memory ownershipAttestations - ) public pure returns (bytes32) { - bytes32 domainSeparator = structHashEIP712Domain(domain); - bytes32 ownershipAttestationsHash = getOwnershipAttestation(ownershipAttestations); - return keccak256(abi.encodePacked("\x19\x01", domainSeparator, ownershipAttestationsHash)); - } - - function structHashEIP712Domain(Domain memory domain) private pure returns (bytes32) { - return - keccak256( - abi.encode( - EIP712DOMAIN_TYPEHASH, - keccak256(bytes(domain.name)), - keccak256(bytes(domain.version)), - domain.chainId, - domain.verifyingContract - ) - ); - } - - function getOwnershipAttestation(OwnershipAttestations memory ownershipAttestations) - public - pure - returns (bytes32) - { - return - keccak256( - abi.encode( - EIP712_OWNERSHIP_ATTESTATION_TYPEHASH, - ownershipAttestations.identifier, - ownershipAttestations.issuer, - ownershipAttestations.account, - ownershipAttestations.signer, - ownershipAttestations.issuedOn - ) - ); - } - - function signAndRegisterAttestation( - bytes32 identifier, - address issuer, - address account, - uint64 issuedOn, - address signer - ) public { - (uint8 v, bytes32 r, bytes32 s) = getSignatureForAttestation( - identifier, - issuer, - account, - issuedOn, - privateKeys[signer], - chainId, - address(federatedAttestations) - ); - - if (issuer != signer && !accounts.isSigner(issuer, signer, AttestationSignerRole)) { - vm.prank(issuer); - accounts.authorizeSigner(signer, AttestationSignerRole); - vm.prank(signer); - accounts.completeSignerAuthorization(issuer, AttestationSignerRole); - } - - vm.prank(issuer); - - federatedAttestations.registerAttestation( - identifier, - issuer, - account, - signer, - issuedOn, - v, - r, - s - ); - } - - function assertAttestationInStorage( - bytes32 identifier, - address issuer, - uint256 attestationIndex, - address account, - uint64 issuedOn, - address signer, - uint256 identifierIndex - ) public { - (address _account, address _signer, uint64 _issuedOn, ) = federatedAttestations - .identifierToAttestations(identifier, issuer, attestationIndex); - - assertEq(_account, account); - assertEq(_signer, signer); - assertEq(uint256(_issuedOn), uint256(issuedOn)); - - bytes32 storedIdentifier = federatedAttestations.addressToIdentifiers( - account, - issuer, - identifierIndex - ); - assertEq(storedIdentifier, identifier); - } - - function assertAttestationNotInStorage( - bytes32 identifier, - address issuer, - address account, - uint256 addressIndex, - uint256 identifierIndex - ) public { - vm.expectRevert(); - federatedAttestations.identifierToAttestations(identifier, issuer, addressIndex); - vm.expectRevert(); - federatedAttestations.addressToIdentifiers(account, issuer, identifierIndex); - } - - function checkAgainstExpectedAttestations( - uint256[] memory expectedCountsPerIssuer, - AttestationTestCase[] memory expectedAttestations, - uint256 expectedPublishedOnLowerBound, - uint256[] memory actualCountsPerIssuer, - address[] memory actualAddresses, - address[] memory actualSigners, - uint64[] memory actualIssuedOns, - uint64[] memory actualPublishedOns - ) public { - assertEq( - actualCountsPerIssuer.length, - expectedCountsPerIssuer.length, - "actualCountsPerIssuer.length" - ); - assertEq(actualAddresses.length, expectedAttestations.length, "actualAddresses.length"); - assertEq(actualSigners.length, expectedAttestations.length, "actualSigners.length"); - assertEq(actualIssuedOns.length, expectedAttestations.length, "actualIssuedOns.length"); - assertEq(actualPublishedOns.length, expectedAttestations.length, "actualPublishedOns.length"); - - for (uint256 i = 0; i < expectedAttestations.length; i++) { - assertEq(actualAddresses[i], expectedAttestations[i].account, "account"); - assertEq(actualSigners[i], expectedAttestations[i].signer, "signer"); - assertEq(actualIssuedOns[i], expectedAttestations[i].issuedOn, "issuedOn"); - assertEq(actualPublishedOns[i] >= expectedPublishedOnLowerBound, true); - } - } - - function bytes32ToHexString(bytes32 data) public pure returns (string memory) { - bytes memory alphabet = "0123456789abcdef"; - - bytes memory str = new bytes(64); // Length of hex string is 32 bytes * 2 characters per byte - for (uint256 i = 0; i < 32; i++) { - // Takes each half-byte of bytes32 data and finds its ASCII character in the alphabet - str[i * 2] = alphabet[uint8(data[i] >> 4)]; - str[1 + i * 2] = alphabet[uint8(data[i] & 0x0f)]; - } - return string(str); - } - - function getAddressFromPrivateKey(uint256 privateKey) public pure returns (address) { - return vm.addr(privateKey); - } - - function activateAddress(address account, uint256 tokenBalance) public { - mockERC20Token.mint(account, tokenBalance); - otherMockERC20Token.mint(account, tokenBalance); - vm.prank(account); - accounts.createAccount(); - } - - function setUp() public { - phoneHash = keccak256(abi.encodePacked(phoneNumber)); - phoneHash2 = keccak256(abi.encodePacked(phoneNumber2)); - - address registryAddress = 0x000000000000000000000000000000000000ce10; - - deployCodeTo("Registry.sol", abi.encode(false), registryAddress); - - attestationsTest = new AttestationsTest(); - mockERC20Token = new MockERC20Token(); - otherMockERC20Token = new MockERC20Token(); - mockElection = new MockElection(); - mockLockedGold = new MockLockedGold(); - mockValidators = new MockValidators(); - random = new MockRandom(); - registry = Registry(registryAddress); - accounts = new Accounts(true); - federatedAttestations = new FederatedAttestations(true); - random.initialize(256); - random.addTestRandomness(0, bytes32(0)); - accounts.initialize(address(registry)); - registry.setAddressFor("Validators", address(mockValidators)); - - callerPK = 0xf2f48ee19680706196e2e339e5da3491186e0c4c5030670656b0e0164837257d; - caller = getAddressFromPrivateKey(callerPK); - - callerPK2 = 0x5d862464fe9303452126c8bc94274b8c5f9874cbd219789b3eb2128075a76f72; - caller2 = getAddressFromPrivateKey(callerPK2); - - callerPK3 = 0xdf02719c4df8b9b8ac7f551fcb5d9ef48fa27eef7a66453879f4d8fdc6e78fb1; - caller3 = getAddressFromPrivateKey(callerPK3); - - // (caller, callerPK) = actorWithPK("caller"); - // (caller2, callerPK2) = actorWithPK("caller2"); - // (caller3, callerPK3) = actorWithPK("caller3"); - (caller4, callerPK4) = actorWithPK("caller4"); - (caller5, callerPK5) = actorWithPK("caller5"); - (caller6, callerPK6) = actorWithPK("caller6"); - (caller7, callerPK7) = actorWithPK("caller7"); - (caller8, callerPK8) = actorWithPK("caller8"); - - privateKeys[caller] = callerPK; - privateKeys[caller2] = callerPK2; - privateKeys[caller3] = callerPK3; - privateKeys[caller4] = callerPK4; - privateKeys[caller5] = callerPK5; - privateKeys[caller6] = callerPK6; - privateKeys[caller7] = callerPK7; - privateKeys[caller8] = callerPK8; - - mockERC20Token.mint(address(this), 10 ether); - - registry.setAddressFor("Election", address(mockElection)); - registry.setAddressFor("LockedGold", address(mockLockedGold)); - registry.setAddressFor("Random", address(random)); - registry.setAddressFor("Accounts", address(accounts)); - - address[] memory mockTokens = new address[](2); - mockTokens[0] = address(mockERC20Token); - mockTokens[1] = address(otherMockERC20Token); - - uint256[] memory attestationsFees = new uint256[](2); - attestationsFees[0] = attestationFee; - attestationsFees[1] = attestationFee; - - attestationsTest.initialize( - address(registry), - attestationExpiryBlocks, - selectIssuersWaitBlocks, - maxAttestations, - mockTokens, - attestationsFees - ); - - account1 = caller7; - signer1 = caller8; - issuer1 = caller; - account2 = caller2; - issuer2 = caller3; - issuer2Singer = caller4; - issuer2Singer2 = caller5; - issuer3 = caller6; - - vm.warp(10 * 60 * 60); // 10 hours - vm.prank(issuer1); - accounts.createAccount(); - vm.prank(issuer2); - accounts.createAccount(); - } - - function setAccountWalletAddress(address account) public { - vm.prank(account); - accounts.setWalletAddress(account, 0, bytes32(0), bytes32(0)); - } -} - -contract FederatedAttestations_EIP712_Ownership_Attestation_Typehash is - FederatedAttestationsFoundryTest -{ - function setUp() public { - super.setUp(); - } - - function test_ShouldHaveSetTheRightTypeHash() public { - bytes32 expectedTypeHash = keccak256( - abi.encodePacked( - "OwnershipAttestation(bytes32 identifier,address issuer,address account,address signer,uint64 issuedOn)" - ) - ); - assertEq(federatedAttestations.EIP712_OWNERSHIP_ATTESTATION_TYPEHASH(), expectedTypeHash); - } -} - -contract FederatedAttestations_Initialize is FederatedAttestationsFoundryTest { - function setUp() public { - super.setUp(); - } - - function test_ShouldHaveSetOwner() public { - vm.prank(caller); - federatedAttestations.initialize(); - assertEq(federatedAttestations.owner(), caller); - } - - function test_ShouldHaveSetTheEIP712DomainSeparator() public { - federatedAttestations.initialize(); - bytes32 expectedDomainSeparator = keccak256( - abi.encode( - keccak256( - "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" - ), - keccak256(bytes("FederatedAttestations")), - keccak256("1.0"), - chainId, - address(federatedAttestations) - ) - ); - - assertEq(federatedAttestations.eip712DomainSeparator(), expectedDomainSeparator); - } - - function test_ShouldEmitTheEIP712DomainSeparatorSet_Event() public { - bytes32 expectedDomainSeparator = keccak256( - abi.encode( - keccak256( - "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" - ), - keccak256(bytes("FederatedAttestations")), - keccak256("1.0"), - chainId, - address(federatedAttestations) - ) - ); - - vm.expectEmit(true, true, true, true); - emit EIP712DomainSeparatorSet(expectedDomainSeparator); - - federatedAttestations.initialize(); - } - - function test_ShouldNotBeCallableAgain() public { - federatedAttestations.initialize(); - vm.expectRevert("contract already initialized"); - federatedAttestations.initialize(); - } -} - -contract FederatedAttestations_LookupAttestations is FederatedAttestationsFoundryTest { - uint256 HOURS_10 = 10 * 60 * 60; - - function setUp() public { - super.setUp(); - federatedAttestations.initialize(); - } - - function test_WhenIdentifierHasNotBeenRegistered_ShouldReturnEmptyList() public { - address[] memory trustedIssuers = new address[](1); - trustedIssuers[0] = caller; - (uint256[] memory countsPerIssuer, address[] memory _accounts, address[] memory signers, uint64[] memory issuedOns, uint64[] memory publishedOns) = federatedAttestations - .lookupAttestations(phoneHash, trustedIssuers); - - uint256[] memory expectedCountsPerIssuer = new uint256[](1); - expectedCountsPerIssuer[0] = 0; - - AttestationTestCase[] memory expectedAttestations = new AttestationTestCase[](0); - uint256 expectedPublishedOnLowerBound = 0; - - checkAgainstExpectedAttestations( - expectedCountsPerIssuer, - expectedAttestations, - expectedPublishedOnLowerBound, - countsPerIssuer, - _accounts, - signers, - issuedOns, - publishedOns - ); - } - - function prepareTest() public { - signAndRegisterAttestation(phoneHash, issuer1, account1, uint64(block.timestamp), signer1); - signAndRegisterAttestation(phoneHash, issuer1, account2, uint64(block.timestamp), signer1); - - signAndRegisterAttestation( - phoneHash, - issuer2, - account1, - uint64(block.timestamp), - issuer2Singer - ); - signAndRegisterAttestation( - phoneHash, - issuer2, - account2, - uint64(block.timestamp), - issuer2Singer2 - ); - } - - function getIssuer1Attestations() public view returns (AttestationTestCase[] memory) { - AttestationTestCase[] memory issuer1Attestations = new AttestationTestCase[](2); - issuer1Attestations[0] = AttestationTestCase(account1, signer1, HOURS_10); - issuer1Attestations[1] = AttestationTestCase(account2, signer1, HOURS_10); - return issuer1Attestations; - } - - function getIssuer2Attestations() public view returns (AttestationTestCase[] memory) { - AttestationTestCase[] memory issuer2Attestations = new AttestationTestCase[](2); - issuer2Attestations[0] = AttestationTestCase(account1, issuer2Singer, HOURS_10); - issuer2Attestations[1] = AttestationTestCase(account2, issuer2Singer2, HOURS_10); - return issuer2Attestations; - } - - function getIssuer2AndIssuer1Attestations() public view returns (AttestationTestCase[] memory) { - AttestationTestCase[] memory issuer2Attestations = new AttestationTestCase[](4); - issuer2Attestations[0] = AttestationTestCase(account1, issuer2Singer, HOURS_10); - issuer2Attestations[1] = AttestationTestCase(account2, issuer2Singer2, HOURS_10); - issuer2Attestations[2] = AttestationTestCase(account1, signer1, HOURS_10); - issuer2Attestations[3] = AttestationTestCase(account2, signer1, HOURS_10); - return issuer2Attestations; - } - - function getPublishedOnLowerBound() public view returns (uint64) { - // Set lower bound to (now - 1 hour) in seconds - return uint64(block.timestamp - 60 * 60); - } - - function test_WhenIdentifierHasBeenRegistered_ShouldReturnEmptyCountAndListIfNoIssuersSpecified() - public - { - prepareTest(); - - address[] memory trustedIssuers = new address[](0); - (uint256[] memory countsPerIssuer, address[] memory _accounts, address[] memory signers, uint64[] memory issuedOns, uint64[] memory publishedOns) = federatedAttestations - .lookupAttestations(phoneHash, trustedIssuers); - - uint256[] memory expectedCountsPerIssuer = new uint256[](0); - AttestationTestCase[] memory expectedAttestations = new AttestationTestCase[](0); - uint256 expectedPublishedOnLowerBound = 0; - - checkAgainstExpectedAttestations( - expectedCountsPerIssuer, - expectedAttestations, - expectedPublishedOnLowerBound, - countsPerIssuer, - _accounts, - signers, - issuedOns, - publishedOns - ); - } - - function test_ShouldReturnAllAttestationsFromOneIssuer() public { - prepareTest(); - - address[] memory trustedIssuers = new address[](1); - trustedIssuers[0] = issuer1; - (uint256[] memory countsPerIssuer, address[] memory _accounts, address[] memory signers, uint64[] memory issuedOns, uint64[] memory publishedOns) = federatedAttestations - .lookupAttestations(phoneHash, trustedIssuers); - - uint256[] memory expectedCountsPerIssuer = new uint256[](1); - expectedCountsPerIssuer[0] = 2; - - checkAgainstExpectedAttestations( - expectedCountsPerIssuer, - getIssuer1Attestations(), - getPublishedOnLowerBound(), - countsPerIssuer, - _accounts, - signers, - issuedOns, - publishedOns - ); - - } - - function test_ShouldReturnEmptyListIfNoAttestationsExistForAnIssuer() public { - prepareTest(); - - address[] memory trustedIssuers = new address[](1); - trustedIssuers[0] = issuer3; - (uint256[] memory countsPerIssuer, address[] memory _accounts, address[] memory signers, uint64[] memory issuedOns, uint64[] memory publishedOns) = federatedAttestations - .lookupAttestations(phoneHash, trustedIssuers); - - uint256[] memory expectedCountsPerIssuer = new uint256[](1); - expectedCountsPerIssuer[0] = 0; - AttestationTestCase[] memory expectedAttestations = new AttestationTestCase[](0); - uint256 expectedPublishedOnLowerBound = 0; - - checkAgainstExpectedAttestations( - expectedCountsPerIssuer, - expectedAttestations, - expectedPublishedOnLowerBound, - countsPerIssuer, - _accounts, - signers, - issuedOns, - publishedOns - ); - } - - function test_ShouldReturnAttestationsFromMultipleIssuersInCorrectOrder() public { - prepareTest(); - - address[] memory trustedIssuers = new address[](3); - trustedIssuers[0] = issuer3; - trustedIssuers[1] = issuer2; - trustedIssuers[2] = issuer1; - (uint256[] memory countsPerIssuer, address[] memory _accounts, address[] memory signers, uint64[] memory issuedOns, uint64[] memory publishedOns) = federatedAttestations - .lookupAttestations(phoneHash, trustedIssuers); - - uint256[] memory expectedCountsPerIssuer = new uint256[](3); - expectedCountsPerIssuer[0] = 0; - expectedCountsPerIssuer[1] = getIssuer2Attestations().length; - expectedCountsPerIssuer[2] = getIssuer1Attestations().length; - - checkAgainstExpectedAttestations( - expectedCountsPerIssuer, - getIssuer2AndIssuer1Attestations(), - getPublishedOnLowerBound(), - countsPerIssuer, - _accounts, - signers, - issuedOns, - publishedOns - ); - } - - function test_WhenIdentifierHasBeenRegisteredAndThenRevoked_ShouldReturnEmptyList() public { - vm.warp(HOURS_10); - signAndRegisterAttestation(phoneHash, issuer1, account1, uint64(block.timestamp), signer1); - vm.prank(issuer1); - federatedAttestations.revokeAttestation(phoneHash, issuer1, account1); - - address[] memory trustedIssuers = new address[](1); - trustedIssuers[0] = issuer1; - (uint256[] memory countsPerIssuer, address[] memory _accounts, address[] memory signers, uint64[] memory issuedOns, uint64[] memory publishedOns) = federatedAttestations - .lookupAttestations(phoneHash, trustedIssuers); - - uint256[] memory expectedCountsPerIssuer = new uint256[](1); - expectedCountsPerIssuer[0] = 0; - AttestationTestCase[] memory expectedAttestations = new AttestationTestCase[](0); - uint256 expectedPublishedOnLowerBound = 0; - - checkAgainstExpectedAttestations( - expectedCountsPerIssuer, - expectedAttestations, - expectedPublishedOnLowerBound, - countsPerIssuer, - _accounts, - signers, - issuedOns, - publishedOns - ); - - } - -} - -contract FederatedAttestations_LookupIdentifiers is FederatedAttestationsFoundryTest { - uint256 HOURS_10 = 10 * 60 * 60; - - function setUp() public { - super.setUp(); - federatedAttestations.initialize(); - } - - function prepareTest_WhenAddressHasBEenRegistered() public { - signAndRegisterAttestation(phoneHash, issuer1, account1, uint64(block.timestamp), signer1); - signAndRegisterAttestation(phoneHash2, issuer1, account1, uint64(block.timestamp), signer1); - - signAndRegisterAttestation( - phoneHash, - issuer2, - account1, - uint64(block.timestamp), - issuer2Singer2 - ); - signAndRegisterAttestation( - phoneHash2, - issuer2, - account1, - uint64(block.timestamp), - issuer2Singer - ); - } - - function getIssuer1IdCases() public view returns (IdentifierTestCase[] memory) { - IdentifierTestCase[] memory issuer1Attestations = new IdentifierTestCase[](2); - issuer1Attestations[0] = IdentifierTestCase(phoneHash, signer1); - issuer1Attestations[1] = IdentifierTestCase(phoneHash2, signer1); - return issuer1Attestations; - } - - function getIssuer2IdCases() public view returns (IdentifierTestCase[] memory) { - IdentifierTestCase[] memory issuer2Attestations = new IdentifierTestCase[](2); - issuer2Attestations[0] = IdentifierTestCase(phoneHash, issuer2Singer2); - issuer2Attestations[1] = IdentifierTestCase(phoneHash2, issuer2Singer); - return issuer2Attestations; - } - - function getIssuer2AndIssuer1IdCasesIdentifiers() public view returns (bytes32[] memory) { - bytes32[] memory idCasesIdentifiers = new bytes32[](4); - idCasesIdentifiers[0] = phoneHash; - idCasesIdentifiers[1] = phoneHash2; - idCasesIdentifiers[2] = phoneHash; - idCasesIdentifiers[3] = phoneHash2; - return idCasesIdentifiers; - } - - function test_WhenAddressHasNotBeenRegistered() public { - address[] memory trustedIssuers = new address[](1); - trustedIssuers[0] = issuer1; - (uint256[] memory countsPerIssuer, bytes32[] memory identifiers) = federatedAttestations - .lookupIdentifiers(account1, trustedIssuers); - uint256[] memory expectedCountsPerIssuer = new uint256[](1); - expectedCountsPerIssuer[0] = 0; - assertEq(expectedCountsPerIssuer, countsPerIssuer); - assertEq(identifiers.length, 0); - } - - function test_WhenAddressHasBeenRegistered_ItShouldReturnEmptyCountIfNoIssuersSpecifier() public { - prepareTest_WhenAddressHasBEenRegistered(); - - address[] memory trustedIssuers = new address[](0); - (uint256[] memory countsPerIssuer, bytes32[] memory identifiers) = federatedAttestations - .lookupIdentifiers(account1, trustedIssuers); - - uint256[] memory expectedCountsPerIssuer = new uint256[](0); - assertEq(expectedCountsPerIssuer, countsPerIssuer); - assertEq(identifiers.length, 0); - } - - function test_WhenAddressHasBeenRegistered_ShouldReturnAllIdentifiersFromOneIssuer() public { - prepareTest_WhenAddressHasBEenRegistered(); - - address[] memory trustedIssuers = new address[](1); - trustedIssuers[0] = issuer1; - (uint256[] memory countsPerIssuer, bytes32[] memory identifiers) = federatedAttestations - .lookupIdentifiers(account1, trustedIssuers); - - uint256[] memory expectedCountsPerIssuer = new uint256[](1); - expectedCountsPerIssuer[0] = 2; - bytes32[] memory expectedIdentifiers = new bytes32[](2); - expectedIdentifiers[0] = phoneHash; - expectedIdentifiers[1] = phoneHash2; - assertEq(expectedCountsPerIssuer, countsPerIssuer); - assertEq(identifiers, expectedIdentifiers); - } - - function test_WhenAddressHasBeenRegistered_ShouldReturnEmptyListIfNoIdentifiersExistForAnIssuerAddress() - public - { - prepareTest_WhenAddressHasBEenRegistered(); - - address[] memory trustedIssuers = new address[](1); - trustedIssuers[0] = issuer3; - (uint256[] memory countsPerIssuer, bytes32[] memory identifiers) = federatedAttestations - .lookupIdentifiers(account1, trustedIssuers); - - uint256[] memory expectedCountsPerIssuer = new uint256[](1); - expectedCountsPerIssuer[0] = 0; - bytes32[] memory expectedIdentifiers = new bytes32[](0); - assertEq(expectedCountsPerIssuer, countsPerIssuer); - assertEq(identifiers, expectedIdentifiers); - } - - function test_WhenAddressHasBeenRegistered_ShouldReturnIdentifiersFromMultipleIssuersInCorrectOrder() - public - { - prepareTest_WhenAddressHasBEenRegistered(); - - address[] memory trustedIssuers = new address[](3); - trustedIssuers[0] = issuer3; - trustedIssuers[1] = issuer2; - trustedIssuers[2] = issuer1; - (uint256[] memory countsPerIssuer, bytes32[] memory identifiers) = federatedAttestations - .lookupIdentifiers(account1, trustedIssuers); - - uint256[] memory expectedCountsPerIssuer = new uint256[](3); - expectedCountsPerIssuer[0] = 0; - expectedCountsPerIssuer[1] = getIssuer2IdCases().length; - expectedCountsPerIssuer[2] = getIssuer1IdCases().length; - assertEq(countsPerIssuer, expectedCountsPerIssuer, "invalid counts"); - - assertEq(identifiers, getIssuer2AndIssuer1IdCasesIdentifiers()); - } - - function test_WhenIdentifierHasBeenRegisteredAndThenRevoked_ShouldReturnEmptyList() public { - vm.warp(HOURS_10); - signAndRegisterAttestation(phoneHash, issuer1, account1, uint64(block.timestamp), signer1); - vm.prank(issuer1); - federatedAttestations.revokeAttestation(phoneHash, issuer1, account1); - - address[] memory trustedIssuers = new address[](1); - trustedIssuers[0] = issuer1; - (uint256[] memory countsPerIssuer, bytes32[] memory identifiers) = federatedAttestations - .lookupIdentifiers(account1, trustedIssuers); - - uint256[] memory expectedCountsPerIssuer = new uint256[](1); - expectedCountsPerIssuer[0] = 0; - bytes32[] memory expectedIdentifiers = new bytes32[](0); - assertEq(expectedCountsPerIssuer, countsPerIssuer); - assertEq(identifiers, expectedIdentifiers); - } -} - -contract FederatedAttestations_ValidateAttestation is FederatedAttestationsFoundryTest { - uint256 HOURS_10 = 10 * 60 * 60; - - uint8 v; - bytes32 r; - bytes32 s; - - function setUp() public { - super.setUp(); - federatedAttestations.initialize(); - } - - function prepareTest_WithAnAuthorizedSigner(address issuer, address signer) public { - vm.prank(issuer); - accounts.authorizeSigner(signer, AttestationSignerRole); - vm.prank(signer); - accounts.completeSignerAuthorization(issuer, AttestationSignerRole); - (v, r, s) = getSignatureForAttestation( - phoneHash, - issuer, - account1, - uint64(block.timestamp), - privateKeys[signer], - chainId, - address(federatedAttestations) - ); - } - - function test_WithAnAuthorizedSigner_ShouldReturnSuccessfullyIfAValidSignatureIsUsed() public { - prepareTest_WithAnAuthorizedSigner(issuer1, signer1); - - federatedAttestations.validateAttestationSig( - phoneHash, - issuer1, - account1, - signer1, - uint64(block.timestamp), - v, - r, - s - ); - } - - function test_WithAnAuthorizedSigner_ShouldReturnFalseIfAnInvalidSignatureIsProvided() public { - prepareTest_WithAnAuthorizedSigner(issuer1, signer1); - - (uint8 v2, bytes32 r2, bytes32 s2) = getSignatureForAttestation( - phoneHash, - issuer1, - account1, - uint64(block.timestamp), - privateKeys[issuer2], - chainId, - address(federatedAttestations) - ); - - vm.expectRevert(); - federatedAttestations.validateAttestationSig( - phoneHash, - issuer1, - account1, - signer1, - uint64(block.timestamp), - v2, - r2, - s2 - ); - } - - function test_WithAnAuthorizedSigner_ShouldFailIfTheProvidedIdentifierIsDifferentFromAttestation() - public - { - prepareTest_WithAnAuthorizedSigner(issuer1, signer1); - - vm.expectRevert(); - federatedAttestations.validateAttestationSig( - phoneHash2, - issuer1, - account1, - signer1, - uint64(block.timestamp), - v, - r, - s - ); - } - - function test_WithAnAuthorizedSigner_ShouldFailIfTheProvidedIssuerIsDifferentFromAttestation() - public - { - prepareTest_WithAnAuthorizedSigner(issuer1, signer1); - - vm.expectRevert(); - federatedAttestations.validateAttestationSig( - phoneHash, - issuer2, - account1, - signer1, - uint64(block.timestamp), - v, - r, - s - ); - } - - function test_WithAnAuthorizedSigner_ShouldFailIfTheProvidedAccountIsDifferentFromAttestation() - public - { - prepareTest_WithAnAuthorizedSigner(issuer1, signer1); - - vm.expectRevert(); - federatedAttestations.validateAttestationSig( - phoneHash, - issuer1, - account2, - signer1, - uint64(block.timestamp), - v, - r, - s - ); - } - - function test_WithAnAuthorizedSigner_ShouldFailIfTheProviderSignerIsDifferentFromAttestation() - public - { - prepareTest_WithAnAuthorizedSigner(issuer1, signer1); - - vm.expectRevert(); - federatedAttestations.validateAttestationSig( - phoneHash, - issuer1, - account1, - issuer2Singer, - uint64(block.timestamp), - v, - r, - s - ); - } - - function test_WithAnAuthorizedSigner_ShouldFailIfTheIssuerIssuedOnIsDifferentFromAttestation() - public - { - prepareTest_WithAnAuthorizedSigner(issuer1, signer1); - - vm.expectRevert(); - federatedAttestations.validateAttestationSig( - phoneHash, - issuer1, - account1, - signer1, - uint64(block.timestamp - 1), - v, - r, - s - ); - } - - function test_ShouldRevertIfTheSignerIsNotAuthorizedAsAnAttestationSignerByTheIssuer() public { - vm.expectRevert(); - federatedAttestations.validateAttestationSig( - phoneHash, - issuer1, - account1, - signer1, - uint64(block.timestamp), - v, - r, - s - ); - } - - function test_ShouldFailIfTheSignerIsAuthorizedAsADifferentRoleByTheIssuer() public { - vm.prank(issuer1); - accounts.authorizeSigner(signer1, RandomRole); - vm.prank(signer1); - accounts.completeSignerAuthorization(issuer1, RandomRole); - - vm.expectRevert(); - federatedAttestations.validateAttestationSig( - phoneHash, - issuer1, - account1, - signer1, - uint64(block.timestamp), - v, - r, - s - ); - } -} - -contract FederatedAttestations_RegisterAttestation is FederatedAttestationsFoundryTest { - uint256 HOURS_10 = 10 * 60 * 60; - - uint8 v; - bytes32 r; - bytes32 s; - - function setUp() public { - super.setUp(); - federatedAttestations.initialize(); - - vm.prank(issuer1); - accounts.authorizeSigner(signer1, AttestationSignerRole); - vm.prank(signer1); - accounts.completeSignerAuthorization(issuer1, AttestationSignerRole); - - (v, r, s) = getSignatureForAttestation( - phoneHash, - issuer1, - account1, - uint64(block.timestamp), - privateKeys[signer1], - chainId, - address(federatedAttestations) - ); - - } - - function test_ShouldEmitAttestationRegisteredForAValidAttestation() public { - vm.expectEmit(true, true, true, true); - emit AttestationRegistered( - phoneHash, - issuer1, - account1, - signer1, - uint64(block.timestamp), - uint64(block.timestamp) - ); - - federatedAttestations.registerAttestation( - phoneHash, - issuer1, - account1, - signer1, - uint64(block.timestamp), - v, - r, - s - ); - } - - function test_ShouldSucceedIfIssuerIsEqualToSigner() public { - signAndRegisterAttestation(phoneHash, issuer1, account1, uint64(block.timestamp), issuer1); - assertAttestationInStorage( - phoneHash, - issuer1, - 0, - account1, - uint64(block.timestamp), - issuer1, - 0 - ); - } - - function test_ShouldRevertIfAnInvalidSignatureIsProvided() public { - (uint8 v2, bytes32 r2, bytes32 s2) = getSignatureForAttestation( - phoneHash, - issuer1, - account1, - uint64(block.timestamp), - privateKeys[issuer2], - chainId, - address(federatedAttestations) - ); - - vm.expectRevert(); - federatedAttestations.registerAttestation( - phoneHash, - issuer1, - account1, - signer1, - uint64(block.timestamp), - v2, - r2, - s2 - ); - } - - function test_ShouldRevertIfSignerHasBeenDeregistered() public { - vm.prank(issuer1); - accounts.removeSigner(signer1, AttestationSignerRole); - vm.expectRevert("not active authorized signer for role"); - - federatedAttestations.registerAttestation( - phoneHash, - issuer1, - account1, - signer1, - uint64(block.timestamp), - v, - r, - s - ); - - } - - function test_ShouldModifyIdentifierToAttestationsAndAddressToIdentifiersAccordingly() public { - assertAttestationNotInStorage(phoneHash, issuer1, account1, 0, 0); - signAndRegisterAttestation(phoneHash, issuer1, account1, uint64(block.timestamp), signer1); - assertAttestationInStorage( - phoneHash, - issuer1, - 0, - account1, - uint64(block.timestamp), - signer1, - 0 - ); - } - - function prepareTest_WhenRegisteringASecondAttestations() public { - federatedAttestations.registerAttestation( - phoneHash, - issuer1, - account1, - signer1, - uint64(block.timestamp), - v, - r, - s - ); - } - - function test_WhenRegisteringASecondAttestations_ShouldModifyIdentifierToAttestationsAndAddressToIdentifiersAccordingly() - public - { - prepareTest_WhenRegisteringASecondAttestations(); - assertAttestationInStorage( - phoneHash, - issuer1, - 0, - account1, - uint64(block.timestamp), - signer1, - 0 - ); - assertAttestationNotInStorage(phoneHash, issuer1, account2, 1, 0); - - signAndRegisterAttestation(phoneHash, issuer1, account2, uint64(block.timestamp), signer1); - assertAttestationInStorage( - phoneHash, - issuer1, - 1, - account2, - uint64(block.timestamp), - signer1, - 0 - ); - } - - function test_WhenRegisteringASecondAttestations_ShouldRevertIfAnAttestationWithTheSame_Issuer_Identifiers_Account_IsUploadedAgain() - public - { - prepareTest_WhenRegisteringASecondAttestations(); - - // Upload the same attestation signed by a different signer, authorized under the same issuer - vm.prank(issuer1); - accounts.authorizeSigner(issuer2Singer2, AttestationSignerRole); - vm.prank(issuer2Singer2); - accounts.completeSignerAuthorization(issuer1, AttestationSignerRole); - - (uint8 v2, bytes32 r2, bytes32 s2) = getSignatureForAttestation( - phoneHash, - issuer1, - account1, - uint64(block.timestamp + 1), - privateKeys[issuer2Singer2], - chainId, - address(federatedAttestations) - ); - - vm.expectRevert("Signature is invalid"); - vm.prank(issuer1); - federatedAttestations.registerAttestation( - phoneHash, - issuer1, - account1, - issuer2Singer2, - uint64(block.timestamp), - v2, - r2, - s2 - ); - } - - function test_WhenRegisteringASecondAttestations_ShouldSucceedWithDifferentIdentifier() public { - prepareTest_WhenRegisteringASecondAttestations(); - - signAndRegisterAttestation(phoneHash2, issuer1, account1, uint64(block.timestamp), signer1); - assertAttestationInStorage( - phoneHash2, - issuer1, - 0, - account1, - uint64(block.timestamp), - signer1, - 1 - ); - } - - function test_WhenRegisteringASecondAttestations_ShouldSucceedWithADifferentIssuer() public { - prepareTest_WhenRegisteringASecondAttestations(); - - signAndRegisterAttestation( - phoneHash, - issuer2, - account1, - uint64(block.timestamp), - issuer2Singer2 - ); - assertAttestationInStorage( - phoneHash, - issuer2, - 0, - account1, - uint64(block.timestamp), - issuer2Singer2, - 0 - ); - - } - - function test_WhenRegisteringASecondAttestations_ShouldSucceedWithADifferentAccount() public { - prepareTest_WhenRegisteringASecondAttestations(); - - signAndRegisterAttestation(phoneHash, issuer1, account2, uint64(block.timestamp), signer1); - assertAttestationInStorage( - phoneHash, - issuer1, - 1, - account2, - uint64(block.timestamp), - signer1, - 0 - ); - - } - - function test_ShouldSucceedIfAnyUserAttemptsToRegisterTheAttestationWithAValidSignature() public { - vm.prank(issuer2); - federatedAttestations.registerAttestation( - phoneHash, - issuer1, - account1, - signer1, - uint64(block.timestamp), - v, - r, - s - ); - } - - function test_ShouldSucceedIfADifferentAttestationSignerAuthorizedByTheSameIssuerRegistersTheAttestation() - public - { - vm.prank(issuer1); - accounts.authorizeSigner(issuer2Singer2, AttestationSignerRole); - vm.prank(issuer2Singer2); - accounts.completeSignerAuthorization(issuer1, AttestationSignerRole); - - vm.prank(issuer2Singer2); - federatedAttestations.registerAttestation( - phoneHash, - issuer1, - account1, - signer1, - uint64(block.timestamp), - v, - r, - s - ); - - assertAttestationInStorage( - phoneHash, - issuer1, - 0, - account1, - uint64(block.timestamp), - signer1, - 0 - ); - } - - function test_ShouldSucceedIfTheIssuerSubmitsTheAttestationDirectly() public { - vm.prank(issuer1); - federatedAttestations.registerAttestationAsIssuer(phoneHash, account1, uint64(block.timestamp)); - - assertAttestationInStorage( - phoneHash, - issuer1, - 0, - account1, - uint64(block.timestamp), - issuer1, - 0 - ); - } - - function test_ShouldSucceedIfIssuerIsNotRegisteredInAccounts() public { - assertEq(accounts.isAccount(address(issuer3)), false); - - vm.prank(issuer3); - federatedAttestations.registerAttestationAsIssuer(phoneHash, account1, uint64(block.timestamp)); - - assertAttestationInStorage( - phoneHash, - issuer3, - 0, - account1, - uint64(block.timestamp), - issuer3, - 0 - ); - } - - function test_ShouldRevertIfMAX_ATTESTATIONS_PER_IDENTIFIERHaveAlreadyBeenRegistered() public { - for (uint256 i = 0; i < federatedAttestations.MAX_ATTESTATIONS_PER_IDENTIFIER(); i++) { - address actor = actor(string(abi.encodePacked(i))); - - vm.prank(issuer1); - federatedAttestations.registerAttestationAsIssuer(phoneHash, actor, uint64(block.timestamp)); - } - - vm.expectRevert("Max attestations already registered for identifier"); - vm.prank(issuer1); - federatedAttestations.registerAttestationAsIssuer(phoneHash, account1, uint64(block.timestamp)); - } - - function test_ShouldRevertIfMAX_IDENTIFIERS_PER_ADDRESSHaveAlreadyBeenRegistered() public { - for (uint256 i = 0; i < federatedAttestations.MAX_ATTESTATIONS_PER_IDENTIFIER(); i++) { - bytes32 newIdentifier = keccak256(abi.encodePacked(i)); - - vm.prank(issuer1); - federatedAttestations.registerAttestationAsIssuer( - newIdentifier, - account1, - uint64(block.timestamp) - ); - } - - vm.expectRevert("Max identifiers already registered for account"); - vm.prank(issuer1); - federatedAttestations.registerAttestationAsIssuer(phoneHash, account1, uint64(block.timestamp)); - } - -} - -contract FederatedAttestations_RevokeAttestation is FederatedAttestationsFoundryTest { - uint256 HOURS_10 = 10 * 60 * 60; - - uint8 v; - bytes32 r; - bytes32 s; - - function setUp() public { - super.setUp(); - federatedAttestations.initialize(); - - vm.prank(issuer1); - accounts.authorizeSigner(signer1, AttestationSignerRole); - vm.prank(signer1); - accounts.completeSignerAuthorization(issuer1, AttestationSignerRole); - - (v, r, s) = getSignatureForAttestation( - phoneHash, - issuer1, - account1, - uint64(block.timestamp), - privateKeys[signer1], - chainId, - address(federatedAttestations) - ); - - vm.prank(issuer1); - federatedAttestations.registerAttestation( - phoneHash, - issuer1, - account1, - signer1, - uint64(block.timestamp), - v, - r, - s - ); - } - - function test_ShouldModifyIdentifierToAttestationsAndAddressToIdentifiersAccordingly() public { - assertAttestationInStorage( - phoneHash, - issuer1, - 0, - account1, - uint64(block.timestamp), - signer1, - 0 - ); - vm.prank(issuer1); - federatedAttestations.revokeAttestation(phoneHash, issuer1, account1); - assertAttestationNotInStorage(phoneHash, issuer1, account1, 0, 0); - } - - function test_ShouldSucceedWhenRevokedByACurrentSignerOfIssuer() public { - vm.prank(issuer1); - federatedAttestations.revokeAttestation(phoneHash, issuer1, account1); - assertAttestationNotInStorage(phoneHash, issuer1, account1, 0, 0); - } - - function test_ShouldRevertWhenSIgnerHasBeenDeregistered() public { - vm.prank(issuer1); - accounts.removeSigner(signer1, AttestationSignerRole); - vm.expectRevert("not active authorized signer for role"); - vm.prank(signer1); - federatedAttestations.revokeAttestation(phoneHash, issuer1, account1); - } - - function test_ShouldEmitAnAttestationRevokedEventAfterSuccessfullyRevoking() public { - vm.expectEmit(true, true, true, true); - emit AttestationRevoked( - phoneHash, - issuer1, - account1, - signer1, - uint64(block.timestamp), - uint64(block.timestamp) - ); - - vm.prank(issuer1); - federatedAttestations.revokeAttestation(phoneHash, issuer1, account1); - } - - function test_ShouldSucceedIfIssuerIsNotRegisteredInAccounts() public { - assertEq(accounts.isAccount(address(issuer3)), false); - - vm.prank(issuer3); - federatedAttestations.registerAttestationAsIssuer(phoneHash, account1, uint64(block.timestamp)); - - assertAttestationInStorage( - phoneHash, - issuer3, - 0, - account1, - uint64(block.timestamp), - issuer3, - 0 - ); - - vm.prank(issuer3); - federatedAttestations.revokeAttestation(phoneHash, issuer3, account1); - assertAttestationNotInStorage(phoneHash, issuer3, account1, 0, 0); - } - - function test_ShouldRevertWhenRevokingAnAttestationThatDoesNotExist() public { - vm.expectRevert("Attestation to be revoked does not exist"); - vm.prank(issuer1); - federatedAttestations.revokeAttestation(phoneHash, issuer1, issuer1); - } - - function test_ShouldSucceedWhenMoreThan1AttestationsAreRegisteredForIdentifierAndIssuer() public { - signAndRegisterAttestation(phoneHash, issuer1, account2, uint64(block.timestamp), signer1); - vm.prank(account2); - federatedAttestations.revokeAttestation(phoneHash, issuer1, account2); - assertAttestationNotInStorage(phoneHash, issuer1, account2, 1, 0); - assertAttestationInStorage( - phoneHash, - issuer1, - 0, - account1, - uint64(block.timestamp), - signer1, - 0 - ); - } - - function test_ShouldSucceedWhenMoreThan1IdentifiersAreRegisteredForAccountAndIssuer() public { - signAndRegisterAttestation(phoneHash2, issuer1, account1, uint64(block.timestamp), signer1); - vm.prank(account1); - federatedAttestations.revokeAttestation(phoneHash2, issuer1, account1); - assertAttestationNotInStorage(phoneHash2, issuer1, account1, 0, 1); - assertAttestationInStorage( - phoneHash, - issuer1, - 0, - account1, - uint64(block.timestamp), - signer1, - 0 - ); - } - - function test_AfterRevokingAnAttestation_ShouldSucceedInRegisteringNewAttestationWithDifferentIdentifier() - public - { - vm.prank(issuer1); - federatedAttestations.revokeAttestation(phoneHash, issuer1, account1); - - signAndRegisterAttestation(phoneHash2, issuer1, account1, uint64(block.timestamp), signer1); - } - - function test_AfterRevokingAnAttestation_ShouldSucceedInRegisteringNewAttestationWithDifferentAccount() - public - { - vm.prank(issuer1); - federatedAttestations.revokeAttestation(phoneHash, issuer1, account1); - - signAndRegisterAttestation(phoneHash, issuer1, account2, uint64(block.timestamp), signer1); - } - - function test_AfterRevokingAnAttestation_ShouldSucceedInRegisteringNewAttestationWithDifferentIssuedOn() - public - { - vm.prank(issuer1); - federatedAttestations.revokeAttestation(phoneHash, issuer1, account1); - - signAndRegisterAttestation(phoneHash, issuer1, account1, uint64(block.timestamp + 1), signer1); - } - - function test_AfterRevokingAnAttestation_ShouldSucceedInRegisteringNewAttestationWithDifferentSigner() - public - { - vm.prank(issuer1); - federatedAttestations.revokeAttestation(phoneHash, issuer1, account1); - - signAndRegisterAttestation( - phoneHash, - issuer1, - account1, - uint64(block.timestamp), - issuer2Singer2 - ); - } - - function test_ShouldRevertWhenInvalidUserAttemptsToRevokeTheAttestation() public { - vm.expectRevert("Sender does not have permission to revoke this attestation"); - vm.prank(issuer2); - federatedAttestations.revokeAttestation(phoneHash, issuer1, account1); - } - - function test_ShouldFailToRegisterARevokedAttestation() public { - vm.prank(issuer1); - federatedAttestations.revokeAttestation(phoneHash, issuer1, account1); - - vm.expectRevert("Attestation has been revoked"); - vm.prank(issuer1); - federatedAttestations.registerAttestation( - phoneHash, - issuer1, - account1, - signer1, - uint64(block.timestamp), - v, - r, - s - ); - } -} - -contract FederatedAttestations_BatchRevokeAttestations is FederatedAttestationsFoundryTest { - function setUp() public { - super.setUp(); - federatedAttestations.initialize(); - - signAndRegisterAttestation(phoneHash, issuer1, account1, uint64(block.timestamp), signer1); - signAndRegisterAttestation( - phoneHash, - issuer1, - account2, - uint64(block.timestamp), - issuer2Singer - ); - signAndRegisterAttestation(phoneHash2, issuer1, account2, uint64(block.timestamp), signer1); - } - - function test_ShouldSucceedIfIssuerBatchRevokesAttestations() public { - bytes32[] memory attestationsToRevoke = new bytes32[](2); - attestationsToRevoke[0] = phoneHash; - attestationsToRevoke[1] = phoneHash2; - - address[] memory accountsToRevoke = new address[](2); - accountsToRevoke[0] = account1; - accountsToRevoke[1] = account2; - - vm.prank(issuer1); - federatedAttestations.batchRevokeAttestations(issuer1, attestationsToRevoke, accountsToRevoke); - - address[] memory trustedIssuers = new address[](1); - trustedIssuers[0] = issuer1; - (uint256[] memory countsPerIssuer, address[] memory _accounts, address[] memory signers, uint64[] memory issuedOns, uint64[] memory publishedOns) = federatedAttestations - .lookupAttestations(phoneHash, trustedIssuers); - - uint256[] memory expectedCountsPerIssuer = new uint256[](1); - expectedCountsPerIssuer[0] = 1; - - AttestationTestCase[] memory expectedAttestations = new AttestationTestCase[](1); - expectedAttestations[0] = AttestationTestCase(account2, issuer2Singer, uint64(block.timestamp)); - uint256 expectedPublishedOnLowerBound = 0; - - checkAgainstExpectedAttestations( - expectedCountsPerIssuer, - expectedAttestations, - expectedPublishedOnLowerBound, - countsPerIssuer, - _accounts, - signers, - issuedOns, - publishedOns - ); - - trustedIssuers = new address[](1); - trustedIssuers[0] = issuer1; - (countsPerIssuer, _accounts, signers, issuedOns, publishedOns) = federatedAttestations - .lookupAttestations(phoneHash2, trustedIssuers); - - expectedCountsPerIssuer = new uint256[](1); - expectedCountsPerIssuer[0] = 0; - - expectedAttestations = new AttestationTestCase[](0); - - checkAgainstExpectedAttestations( - expectedCountsPerIssuer, - expectedAttestations, - expectedPublishedOnLowerBound, - countsPerIssuer, - _accounts, - signers, - issuedOns, - publishedOns - ); - } - - function test_ShouldSucceedRegardlessOfOrderOfAttestationsAndIdentifiers() public { - bytes32[] memory attestationsToRevoke = new bytes32[](2); - attestationsToRevoke[0] = phoneHash2; - attestationsToRevoke[1] = phoneHash; - - address[] memory accountsToRevoke = new address[](2); - accountsToRevoke[0] = account2; - accountsToRevoke[1] = account1; - - vm.prank(issuer1); - federatedAttestations.batchRevokeAttestations(issuer1, attestationsToRevoke, accountsToRevoke); - - address[] memory trustedIssuers = new address[](1); - trustedIssuers[0] = issuer1; - (uint256[] memory countsPerIssuer, address[] memory _accounts, address[] memory signers, uint64[] memory issuedOns, uint64[] memory publishedOns) = federatedAttestations - .lookupAttestations(phoneHash, trustedIssuers); - - uint256[] memory expectedCountsPerIssuer = new uint256[](1); - expectedCountsPerIssuer[0] = 1; - - AttestationTestCase[] memory expectedAttestations = new AttestationTestCase[](1); - expectedAttestations[0] = AttestationTestCase(account2, issuer2Singer, uint64(block.timestamp)); - uint256 expectedPublishedOnLowerBound = 0; - - checkAgainstExpectedAttestations( - expectedCountsPerIssuer, - expectedAttestations, - expectedPublishedOnLowerBound, - countsPerIssuer, - _accounts, - signers, - issuedOns, - publishedOns - ); - - trustedIssuers = new address[](1); - trustedIssuers[0] = issuer1; - (countsPerIssuer, _accounts, signers, issuedOns, publishedOns) = federatedAttestations - .lookupAttestations(phoneHash2, trustedIssuers); - - expectedCountsPerIssuer = new uint256[](1); - expectedCountsPerIssuer[0] = 0; - - expectedAttestations = new AttestationTestCase[](0); - - checkAgainstExpectedAttestations( - expectedCountsPerIssuer, - expectedAttestations, - expectedPublishedOnLowerBound, - countsPerIssuer, - _accounts, - signers, - issuedOns, - publishedOns - ); - } - - function test_ShouldSucceedIfCurrentlyRegisteredSignerOfIssuerBatchRevokesAttestations() public { - bytes32[] memory attestationsToRevoke = new bytes32[](2); - attestationsToRevoke[0] = phoneHash2; - attestationsToRevoke[1] = phoneHash; - - address[] memory accountsToRevoke = new address[](2); - accountsToRevoke[0] = account2; - accountsToRevoke[1] = account1; - - vm.prank(signer1); - federatedAttestations.batchRevokeAttestations(issuer1, attestationsToRevoke, accountsToRevoke); - - address[] memory trustedIssuers = new address[](1); - trustedIssuers[0] = issuer1; - (uint256[] memory countsPerIssuer, address[] memory _accounts, address[] memory signers, uint64[] memory issuedOns, uint64[] memory publishedOns) = federatedAttestations - .lookupAttestations(phoneHash, trustedIssuers); - - uint256[] memory expectedCountsPerIssuer = new uint256[](1); - expectedCountsPerIssuer[0] = 1; - - AttestationTestCase[] memory expectedAttestations = new AttestationTestCase[](1); - expectedAttestations[0] = AttestationTestCase(account2, issuer2Singer, uint64(block.timestamp)); - uint256 expectedPublishedOnLowerBound = 0; - - checkAgainstExpectedAttestations( - expectedCountsPerIssuer, - expectedAttestations, - expectedPublishedOnLowerBound, - countsPerIssuer, - _accounts, - signers, - issuedOns, - publishedOns - ); - - trustedIssuers = new address[](1); - trustedIssuers[0] = issuer1; - (countsPerIssuer, _accounts, signers, issuedOns, publishedOns) = federatedAttestations - .lookupAttestations(phoneHash2, trustedIssuers); - - expectedCountsPerIssuer = new uint256[](1); - expectedCountsPerIssuer[0] = 0; - - expectedAttestations = new AttestationTestCase[](0); - - checkAgainstExpectedAttestations( - expectedCountsPerIssuer, - expectedAttestations, - expectedPublishedOnLowerBound, - countsPerIssuer, - _accounts, - signers, - issuedOns, - publishedOns - ); - } - - function test_ShouldSucceedIfIssuerIsNotRegisteredInAccounts() public { - assertEq(accounts.isAccount(address(issuer3)), false); - - vm.prank(issuer3); - federatedAttestations.registerAttestationAsIssuer(phoneHash, account1, uint64(block.timestamp)); - - assertAttestationInStorage( - phoneHash, - issuer3, - 0, - account1, - uint64(block.timestamp), - issuer3, - 0 - ); - - bytes32[] memory attestationsToRevoke = new bytes32[](1); - attestationsToRevoke[0] = phoneHash; - - address[] memory accountsToRevoke = new address[](1); - accountsToRevoke[0] = account1; - - vm.prank(issuer3); - federatedAttestations.batchRevokeAttestations(issuer3, attestationsToRevoke, accountsToRevoke); - - assertAttestationNotInStorage(phoneHash, issuer3, account1, 0, 0); - } - - function test_ShouldRevertIfDeregisteredSignerOfIssuerBatchRevokesAttestations() public { - vm.prank(issuer1); - accounts.removeSigner(signer1, AttestationSignerRole); - vm.expectRevert("not active authorized signer for role"); - - bytes32[] memory attestationsToRevoke = new bytes32[](2); - attestationsToRevoke[0] = phoneHash2; - attestationsToRevoke[1] = phoneHash; - - address[] memory accountsToRevoke = new address[](2); - accountsToRevoke[0] = account2; - accountsToRevoke[1] = account1; - - vm.prank(signer1); - federatedAttestations.batchRevokeAttestations(issuer1, attestationsToRevoke, accountsToRevoke); - } - - function test_ShouldRevertIfIdentifiersLengthIsNotEqualAccountsLength() public { - bytes32[] memory attestationsToRevoke = new bytes32[](2); - attestationsToRevoke[0] = phoneHash2; - attestationsToRevoke[1] = phoneHash; - - address[] memory accountsToRevoke = new address[](1); - accountsToRevoke[0] = account2; - - vm.prank(signer1); - vm.expectRevert("Unequal number of identifiers and accounts"); - federatedAttestations.batchRevokeAttestations(issuer1, attestationsToRevoke, accountsToRevoke); - } - - function test_ShouldRevertIfOneOfTheIdentifierAccountPairsIsInvalid() public { - bytes32[] memory attestationsToRevoke = new bytes32[](2); - attestationsToRevoke[0] = phoneHash2; - attestationsToRevoke[1] = phoneHash2; - - address[] memory accountsToRevoke = new address[](2); - accountsToRevoke[0] = account2; - accountsToRevoke[1] = account1; - - vm.prank(signer1); - vm.expectRevert("Attestation to be revoked does not exist"); - federatedAttestations.batchRevokeAttestations(issuer1, attestationsToRevoke, accountsToRevoke); - } -} diff --git a/packages/protocol/test-sol/identity/IdentityProxy.t.sol b/packages/protocol/test-sol/identity/IdentityProxy.t.sol deleted file mode 100644 index f63216949..000000000 --- a/packages/protocol/test-sol/identity/IdentityProxy.t.sol +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.5.13; - -import "celo-foundry/Test.sol"; -import "@celo-contracts/identity/IdentityProxy.sol"; -import "@celo-contracts/identity/test/IdentityProxyTest.sol"; - -contract IdentityProxyTestFoundry is Test { - IdentityProxy identityProxy; - IdentityProxyTest identityProxyTest; - - address randomActor = actor("randomActor"); - - function setUp() public { - identityProxy = new IdentityProxy(); - identityProxyTest = new IdentityProxyTest(); - } -} - -contract IdentityProxyTestMakeCall is IdentityProxyTestFoundry { - function setUp() public { - super.setUp(); - } - - function test_CanBeUsedToForwardCall() public { - uint256 value = 42; - identityProxy.makeCall( - address(identityProxyTest), - abi.encodeWithSignature("setX(uint256)", value) - ); - assertEq(identityProxyTest.x(), value); - } - - function test_MakesCallsFromAddressOfTheProxy() public { - identityProxy.makeCall(address(identityProxyTest), abi.encodeWithSignature("callMe()")); - assertEq(identityProxyTest.lastAddress(), address(identityProxy)); - } - - function test_CannotBeCalledByAnyoneOtherThanTheOriginalDeployer() public { - bytes memory txData = abi.encodeWithSignature("callMe()"); - vm.expectRevert("Only callable by original deployer"); - vm.prank(randomActor); - identityProxy.makeCall(address(identityProxyTest), txData); - } -} diff --git a/packages/protocol/test-sol/identity/IdentityProxyHub.t.sol b/packages/protocol/test-sol/identity/IdentityProxyHub.t.sol deleted file mode 100644 index a5091fdbe..000000000 --- a/packages/protocol/test-sol/identity/IdentityProxyHub.t.sol +++ /dev/null @@ -1,238 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.5.13; - -import "celo-foundry/Test.sol"; -import "@celo-contracts/identity/IdentityProxy.sol"; -import "@celo-contracts/identity/IdentityProxyHub.sol"; -import "@celo-contracts/identity/test/IdentityProxyTest.sol"; -import "@celo-contracts/identity/test/MockAttestations.sol"; -import "@celo-contracts/common/Registry.sol"; - -contract IdentityProxyHubTest is Test { - IdentityProxy identityProxy; - IdentityProxyTest identityProxyTest; - IdentityProxyHub identityProxyHub; - MockAttestations mockAttestations; - Registry registry; - - address randomActor = actor("randomActor"); - - bytes32 identifier = keccak256( - "0x00000000000000000000000000000000000000000000000000000000babecafe" - ); - - function setUp() public { - identityProxy = new IdentityProxy(); - identityProxyTest = new IdentityProxyTest(); - identityProxyHub = new IdentityProxyHub(); - mockAttestations = new MockAttestations(); - registry = new Registry(true); - registry.initialize(); - registry.setAddressFor("Attestations", address(mockAttestations)); - identityProxyHub.setRegistry(address(registry)); - } - - function computeCreate2Address( - bytes32 salt, - address deployerAddress, - bytes memory contractBytecode - ) public pure returns (address) { - bytes32 bytecodeHash = keccak256(contractBytecode); - bytes32 hash = keccak256(abi.encodePacked(bytes1(0xff), deployerAddress, salt, bytecodeHash)); - - return - address( - uint160(uint256(hash) & 0x000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) - ); - } - - /** - * Returns bytecode at address - * @param _addr The address to get the code from - */ - function at(address _addr) public view returns (bytes memory o_code) { - assembly { - // retrieve the size of the code - let size := extcodesize(_addr) - // allocate output byte array - // by using o_code = new bytes(size) - o_code := mload(0x40) - // new "memory end" including padding - mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f)))) - // store length in memory - mstore(o_code, size) - // actually retrieve the code, this needs assembly - extcodecopy(_addr, add(o_code, 0x20), 0, size) - } - } -} - -contract IdentityProxyTestGetIdenityProxy is IdentityProxyHubTest { - function setUp() public { - super.setUp(); - } - - function test_ReturnsTheCorrectCREATE2Address() public { - bytes memory bytecode = type(IdentityProxy).creationCode; - address expectedAddress = computeCreate2Address( - identifier, - address(identityProxyHub), - bytecode - ); - IdentityProxy identityProxyReturned = identityProxyHub.getOrDeployIdentityProxy(identifier); - assertEq(expectedAddress, address(identityProxyReturned)); - } - - function test_ReturnsTheAddressOfAnIdentityProxy() public { - IdentityProxy identityProxyReturned = identityProxyHub.getOrDeployIdentityProxy(identifier); - identityProxyHub.getOrDeployIdentityProxy(identifier); - - bytes memory deployedCode = vm.getDeployedCode("IdentityProxy.sol:IdentityProxy"); - assertEq(deployedCode, at(address(identityProxyReturned))); - } -} - -contract IdentityProxyTestMakeCall_Failures is IdentityProxyHubTest { - address identityProxyAddress; - - function setUp() public { - super.setUp(); - identityProxyAddress = address(identityProxyHub.getOrDeployIdentityProxy(identifier)); - } - - function test_FailsToCallIfSenderDoesNotHaveAtLeast3AttestationCompletions() public { - mockAttestations.complete(identifier, 0, bytes32(0), bytes32(0)); - mockAttestations.complete(identifier, 0, bytes32(0), bytes32(0)); - - bytes memory txData = abi.encodeWithSignature("callMe()"); - vm.expectRevert("does not pass identity heuristic"); - identityProxyHub.makeCall(identifier, address(identityProxyTest), txData); - } - - function test_FailsToCallIfSenderDoesNotHaveMoreThan50PercentAttestationCompletions() public { - mockAttestations.complete(identifier, 0, bytes32(0), bytes32(0)); - mockAttestations.complete(identifier, 0, bytes32(0), bytes32(0)); - mockAttestations.complete(identifier, 0, bytes32(0), bytes32(0)); - - mockAttestations.request(identifier, 0, bytes32(0), bytes32(0)); - mockAttestations.request(identifier, 0, bytes32(0), bytes32(0)); - mockAttestations.request(identifier, 0, bytes32(0), bytes32(0)); - mockAttestations.request(identifier, 0, bytes32(0), bytes32(0)); - mockAttestations.request(identifier, 0, bytes32(0), bytes32(0)); - mockAttestations.request(identifier, 0, bytes32(0), bytes32(0)); - mockAttestations.request(identifier, 0, bytes32(0), bytes32(0)); - - bytes memory txData = abi.encodeWithSignature("callMe()"); - vm.expectRevert("does not pass identity heuristic"); - identityProxyHub.makeCall(identifier, address(identityProxyTest), txData); - } - - function test_FailsToCallIfAnotherAddressHasMoreAttestationsCompleted() public { - mockAttestations.complete(identifier, 0, bytes32(0), bytes32(0)); - mockAttestations.complete(identifier, 0, bytes32(0), bytes32(0)); - mockAttestations.complete(identifier, 0, bytes32(0), bytes32(0)); - - vm.prank(randomActor); - mockAttestations.complete(identifier, 0, bytes32(0), bytes32(0)); - vm.prank(randomActor); - mockAttestations.complete(identifier, 0, bytes32(0), bytes32(0)); - vm.prank(randomActor); - mockAttestations.complete(identifier, 0, bytes32(0), bytes32(0)); - vm.prank(randomActor); - mockAttestations.complete(identifier, 0, bytes32(0), bytes32(0)); - - bytes memory txData = abi.encodeWithSignature("callMe()"); - vm.expectRevert("does not pass identity heuristic"); - identityProxyHub.makeCall(identifier, address(identityProxyTest), txData); - } -} - -contract IdentityProxyTestMakeCall_WhenCalledByContractRelatedToTheIdentifier is - IdentityProxyHubTest -{ - address identityProxyAddress; - - function setUp() public { - super.setUp(); - - identityProxyAddress = address(identityProxyHub.getOrDeployIdentityProxy(identifier)); - - mockAttestations.complete(identifier, 0, bytes32(0), bytes32(0)); - mockAttestations.complete(identifier, 0, bytes32(0), bytes32(0)); - mockAttestations.complete(identifier, 0, bytes32(0), bytes32(0)); - } - - function test_ForwardsCallToTheDestination() public { - uint256 value = 42; - identityProxyHub.makeCall( - identifier, - address(identityProxyTest), - abi.encodeWithSignature("setX(uint256)", value) - ); - - assertEq(identityProxyTest.x(), value); - } - - function test_ForwardsCallToEvenWhenCompletedRationIsCloseTo50Percent() public { - mockAttestations.request(identifier, 0, bytes32(0), bytes32(0)); - mockAttestations.request(identifier, 0, bytes32(0), bytes32(0)); - mockAttestations.request(identifier, 0, bytes32(0), bytes32(0)); - mockAttestations.request(identifier, 0, bytes32(0), bytes32(0)); - mockAttestations.request(identifier, 0, bytes32(0), bytes32(0)); - - uint256 value = 42; - identityProxyHub.makeCall( - identifier, - address(identityProxyTest), - abi.encodeWithSignature("setX(uint256)", value) - ); - - assertEq(identityProxyTest.x(), value); - } - - function test_ForwardsCallAsLongAsNoOtherAddressHasMoreCompletions() public { - vm.prank(randomActor); - mockAttestations.complete(identifier, 0, bytes32(0), bytes32(0)); - vm.prank(randomActor); - mockAttestations.complete(identifier, 0, bytes32(0), bytes32(0)); - vm.prank(randomActor); - mockAttestations.complete(identifier, 0, bytes32(0), bytes32(0)); - - uint256 value = 42; - identityProxyHub.makeCall( - identifier, - address(identityProxyTest), - abi.encodeWithSignature("setX(uint256)", value) - ); - - assertEq(identityProxyTest.x(), value); - } - - function test_ForwardsCallToProxyRelatedToIdentifier() public { - uint256 value = 42; - identityProxyHub.makeCall( - identifier, - address(identityProxyTest), - abi.encodeWithSignature("callMe()", value) - ); - - assertEq(identityProxyTest.lastAddress(), identityProxyAddress); - } - - function test_CanSendAPayment() public { - uint256 balanceBefore = address(identityProxyTest).balance; - identityProxyHub.makeCall.value(100)( - identifier, - address(identityProxyTest), - abi.encodeWithSignature("payMe()") - ); - - uint256 proxyBalance = identityProxyAddress.balance; - uint256 balanceAfter = address(identityProxyTest).balance; - - assertEq(balanceBefore, 0); - assertEq(proxyBalance, 0); - assertEq(balanceAfter, 100); - } -} - diff --git a/packages/protocol/test-sol/identity/OdisPayments.t.sol b/packages/protocol/test-sol/identity/OdisPayments.t.sol deleted file mode 100644 index 423103c22..000000000 --- a/packages/protocol/test-sol/identity/OdisPayments.t.sol +++ /dev/null @@ -1,143 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.5.13; -pragma experimental ABIEncoderV2; - -import "celo-foundry/Test.sol"; -import "@celo-contracts/identity/OdisPayments.sol"; -import { StableToken } from "../../lib/mento-core/contracts/StableToken.sol"; -import "@celo-contracts/common/Registry.sol"; -import "@celo-contracts/common/Freezer.sol"; - -contract OdisPaymentsFoundryTest is Test { - uint256 FIXED1 = 1000000000000000000000000; - uint256 SECONDS_IN_A_DAY = 60 * 60 * 24; - uint256 startingBalanceCUSD = 1000; - - Registry registry; - Freezer freezer; - OdisPayments odisPayments; - StableToken stableToken; - - address sender; - address receiver; - - event PaymentMade(address indexed account, uint256 valueInCUSD); - - function setUp() public { - address registryAddress = 0x000000000000000000000000000000000000ce10; - - deployCodeTo("Registry.sol", abi.encode(false), registryAddress); - - registry = Registry(registryAddress); - freezer = new Freezer(true); - odisPayments = new OdisPayments(true); - stableToken = new StableToken(true); - - sender = actor("sender"); - receiver = actor("receiver"); - - odisPayments.initialize(); - registry.setAddressFor("StableToken", address(stableToken)); - - address[] memory addresses = new address[](2); - addresses[0] = address(this); - addresses[1] = sender; - - uint256[] memory initBalances = new uint256[](2); - initBalances[0] = startingBalanceCUSD; - initBalances[1] = startingBalanceCUSD; - - stableToken.initialize( - "Celo Dollar", - "cUSD", - 18, - address(registry), - FIXED1, - SECONDS_IN_A_DAY, - // Initialize owner and sender with balances - addresses, - initBalances, - "Exchange" // USD - ); - - freezer.initialize(); - registry.setAddressFor("Freezer", address(freezer)); - } -} - -contract OdisPaymentsFoundryTest_Initialize is OdisPaymentsFoundryTest { - function setUp() public { - super.setUp(); - } - - function test_ShouldHaveSetOwner() public { - assertEq(odisPayments.owner(), address(this)); - } - - function test_ShouldNotBeCallableAgain() public { - vm.expectRevert("contract already initialized"); - odisPayments.initialize(); - } -} - -contract OdisPaymentsFoundryTest_PayInCUSD is OdisPaymentsFoundryTest { - uint256 valueApprovedForTransfer = 10; - - function setUp() public { - super.setUp(); - - vm.prank(sender); - stableToken.approve(address(odisPayments), valueApprovedForTransfer); - - assertEq(stableToken.balanceOf(sender), startingBalanceCUSD); - } - - function checkStatecUSD(address cusdSender, address odisPaymentReceiver, uint256 totalValueSent) - public - { - assertEq(stableToken.balanceOf(cusdSender), startingBalanceCUSD - totalValueSent); - assertEq(stableToken.balanceOf(address(odisPayments)), totalValueSent); - assertEq(odisPayments.totalPaidCUSD(odisPaymentReceiver), totalValueSent); - } - - function test_ShouldAllowSenderToMakeAPaymentOnTheirBehalf() public { - vm.prank(sender); - odisPayments.payInCUSD(sender, valueApprovedForTransfer); - checkStatecUSD(sender, sender, valueApprovedForTransfer); - } - - function test_ShouldAllowSenderToMakeAPaymentForAnotherAccount() public { - vm.prank(sender); - odisPayments.payInCUSD(receiver, valueApprovedForTransfer); - checkStatecUSD(sender, receiver, valueApprovedForTransfer); - } - - function test_ShouldAllowSenderToMakeMultiplePaymentToTheContract() public { - uint256 valueForSecondTransfer = 5; - uint256 valueForFirstTransfer = valueApprovedForTransfer - valueForSecondTransfer; - - vm.prank(sender); - odisPayments.payInCUSD(sender, valueForFirstTransfer); - checkStatecUSD(sender, sender, valueForFirstTransfer); - - vm.prank(sender); - odisPayments.payInCUSD(sender, valueForSecondTransfer); - checkStatecUSD(sender, sender, valueApprovedForTransfer); - } - - function test_ShouldEmitPaymentMadeEvent() public { - vm.expectEmit(true, true, true, true); - emit PaymentMade(receiver, valueApprovedForTransfer); - - vm.prank(sender); - odisPayments.payInCUSD(receiver, valueApprovedForTransfer); - } - - function test_ShouldRevertIfTransferFails() public { - vm.expectRevert("SafeERC20: low-level call failed"); - vm.prank(sender); - odisPayments.payInCUSD(sender, valueApprovedForTransfer + 1); - - assertEq(odisPayments.totalPaidCUSD(sender), 0); - } -} diff --git a/packages/protocol/test-sol/identity/Random.t.sol b/packages/protocol/test-sol/identity/Random.t.sol deleted file mode 100644 index bc021743b..000000000 --- a/packages/protocol/test-sol/identity/Random.t.sol +++ /dev/null @@ -1,250 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.5.13; - -import "celo-foundry/Test.sol"; - -// Contract to test -import "@celo-contracts/identity/Random.sol"; -import "@celo-contracts/identity/test/RandomTest.sol"; - -contract SetRandomnessRetentionWindow is Test { - event RandomnessBlockRetentionWindowSet(uint256 value); - - RandomTest random; - - function setUp() public { - random = new RandomTest(); - random.initialize(256); - } - - function test_ShouldSetTheVariable() public { - random.setRandomnessBlockRetentionWindow(1000); - assertEq(random.randomnessBlockRetentionWindow(), 1000); - } - - function test_ShouldEmitTheEvent() public { - vm.expectEmit(true, true, true, true); - emit RandomnessBlockRetentionWindowSet(1000); - random.setRandomnessBlockRetentionWindow(1000); - } - - function testRevert_OnlyOwnerCanSet() public { - vm.expectRevert("Ownable: caller is not the owner"); - vm.prank(address(0x45)); - random.setRandomnessBlockRetentionWindow(1000); - } -} - -contract AddTestRandomness is Test { - uint256 constant RETENTION_WINDOW = 5; - uint256 constant EPOCH_SIZE = 10; - - RandomTest random; - - function setUp() public { - random = new RandomTest(); - random.initialize(256); - } - - function test_ShouldBeAbleToSimulateAddingRandomness() public { - random.addTestRandomness(1, 0x0000000000000000000000000000000000000000000000000000000000000001); - random.addTestRandomness(2, 0x0000000000000000000000000000000000000000000000000000000000000002); - random.addTestRandomness(3, 0x0000000000000000000000000000000000000000000000000000000000000003); - random.addTestRandomness(4, 0x0000000000000000000000000000000000000000000000000000000000000004); - assertEq( - 0x0000000000000000000000000000000000000000000000000000000000000001, - random.getTestRandomness(1, 4) - ); - assertEq( - 0x0000000000000000000000000000000000000000000000000000000000000002, - random.getTestRandomness(2, 4) - ); - assertEq( - 0x0000000000000000000000000000000000000000000000000000000000000003, - random.getTestRandomness(3, 4) - ); - assertEq( - 0x0000000000000000000000000000000000000000000000000000000000000004, - random.getTestRandomness(4, 4) - ); - } - - function setUpWhenChangingHistorySmaller() private { - random.addTestRandomness(1, 0x0000000000000000000000000000000000000000000000000000000000000001); - random.addTestRandomness(2, 0x0000000000000000000000000000000000000000000000000000000000000002); - random.addTestRandomness(3, 0x0000000000000000000000000000000000000000000000000000000000000003); - random.addTestRandomness(4, 0x0000000000000000000000000000000000000000000000000000000000000004); - random.setRandomnessBlockRetentionWindow(2); - } - - function test_canStillAddRandomness_whenChangingHistorySmaller() public { - setUpWhenChangingHistorySmaller(); - random.addTestRandomness(5, 0x0000000000000000000000000000000000000000000000000000000000000005); - assertEq( - 0x0000000000000000000000000000000000000000000000000000000000000005, - random.getTestRandomness(5, 5) - ); - } - - function test_cannotReadOldBlocks_whenChangingHistorySmaller() public { - setUpWhenChangingHistorySmaller(); - vm.expectRevert("Cannot query randomness older than the stored history"); - random.getTestRandomness(3, 5); - } - - function setUpWhenChangingHistoryLarger() private { - random.setRandomnessBlockRetentionWindow(2); - random.addTestRandomness(1, 0x0000000000000000000000000000000000000000000000000000000000000001); - random.addTestRandomness(2, 0x0000000000000000000000000000000000000000000000000000000000000002); - random.addTestRandomness(3, 0x0000000000000000000000000000000000000000000000000000000000000003); - random.addTestRandomness(4, 0x0000000000000000000000000000000000000000000000000000000000000004); - random.setRandomnessBlockRetentionWindow(4); - } - - function test_CanStillAddRandomness_WhenChangingHistoryLarger() public { - setUpWhenChangingHistoryLarger(); - random.addTestRandomness(5, 0x0000000000000000000000000000000000000000000000000000000000000005); - assertEq( - 0x0000000000000000000000000000000000000000000000000000000000000005, - random.getTestRandomness(5, 5) - ); - } - - function test_CannotReadOldBlocks_WhenChangingHistoryLarger() public { - setUpWhenChangingHistoryLarger(); - vm.expectRevert("Cannot query randomness older than the stored history"); - random.getTestRandomness(1, 5); - } - - function test_OldValuesArePreserved_WhenChangingHistoryLarger() public { - setUpWhenChangingHistoryLarger(); - random.addTestRandomness(5, 0x0000000000000000000000000000000000000000000000000000000000000005); - random.addTestRandomness(6, 0x0000000000000000000000000000000000000000000000000000000000000006); - assertEq( - 0x0000000000000000000000000000000000000000000000000000000000000003, - random.getTestRandomness(3, 6) - ); - } - - function setUpWhenRelyingOnTheLastBlockOfEachEpochsRandomness() - private - returns (uint256 lastBlockOfEpoch) - { - bytes32 defaultValue = 0x0000000000000000000000000000000000000000000000000000000000000002; - bytes32 valueForLastBlockOfEpoch = 0x0000000000000000000000000000000000000000000000000000000000000001; - - ph.setEpochSize(EPOCH_SIZE); - random.setRandomnessBlockRetentionWindow(RETENTION_WINDOW); - - // Epoch - // [1 , 2 , 2 , 3 ] - // Blocks - // [EPOCH_SIZE, EPOCH_SIZE+1... EPOCH_SIZE+n, 2 * EPOCH_SIZE, 2 * EPOCH_SIZE + 1... 2 * EPOCH_SIZE + RETENTION_WINDOW-1] - - // go to last block of epoch 1 - vm.roll(EPOCH_SIZE); - // Add randomness to epoch's last block - random.addTestRandomness(block.number, valueForLastBlockOfEpoch); - - // Add a different randomness to all but last epoch blocks - for (uint256 i = 0; i < EPOCH_SIZE - 1; i++) { - vm.roll(block.number + 1); - random.addTestRandomness(block.number, defaultValue); - } - - // Add randomness to epoch's last block - vm.roll(block.number + 1); - random.addTestRandomness(block.number, valueForLastBlockOfEpoch); - - // Now we add `RETENTION_WINDOW` worth of blocks' randomness to flush out the new lastEpochBlock - // This means we can test `lastEpochBlock` stores epoch i+1's last block, - // and we test that epoch i's last block is not retained. - for (uint256 i = 0; i < RETENTION_WINDOW + 1; i++) { - vm.roll(block.number + 1); - random.addTestRandomness(block.number, defaultValue); - } - - // vm.roll(block.number + 1); - return EPOCH_SIZE * 2; - } - - function test_shouldRetainTheLastEpochBlocksRandomness_WhenRelyingOnTheLastBlockOfEachEpochsRandomness() - public - { - uint256 lastBlockOfEpoch = setUpWhenRelyingOnTheLastBlockOfEachEpochsRandomness(); - - // Get start of epoch and then subtract one for last block of previous epoch - assertEq( - 0x0000000000000000000000000000000000000000000000000000000000000001, - random.getTestRandomness(lastBlockOfEpoch, block.number) - ); - } - - function test_shouldRetainTheUsualRetentionWindowWorthOfBlocks_WhenRelyingOnTheLastBlockOfEachEpochsRandomness() - public - { - setUpWhenRelyingOnTheLastBlockOfEachEpochsRandomness(); - - for (uint256 i = 0; i < RETENTION_WINDOW; i++) { - assertEq( - random.getTestRandomness(block.number - i, block.number), - 0x0000000000000000000000000000000000000000000000000000000000000002 - ); - } - } - - function test_shouldStillNotRetainOtherBlocksNotCoveredByTheRetentionWindow_WhenRelyingOnTheLastBlockOfEachEpochsRandomness() - public - { - setUpWhenRelyingOnTheLastBlockOfEachEpochsRandomness(); - vm.expectRevert("Cannot query randomness older than the stored history"); - random.getTestRandomness(block.number - RETENTION_WINDOW, block.number); - } - - function test_shouldNotRetainTheLastEpochBlockOfPreviousEpochs_WhenRelyingOnTheLastBlockOfEachEpochsRandomness() - public - { - uint256 lastBlockOfEpoch = setUpWhenRelyingOnTheLastBlockOfEachEpochsRandomness(); - - vm.expectRevert("Cannot query randomness older than the stored history"); - random.getTestRandomness(lastBlockOfEpoch - EPOCH_SIZE, block.number); - } -} - -contract RevealAndCommit is Test { - address constant ACCOUNT = address(0x01); - bytes32 constant RANDONMESS = bytes32(uint256(0x00)); - - RandomTest random; - - function setUp() public { - random = new RandomTest(); - random.initialize(256); - random.setRandomnessBlockRetentionWindow(256); - } - - function commitmentFor(uint256 value) private pure returns (bytes32) { - return keccak256(abi.encodePacked(bytes32(value))); - } - - function testRevert_CannotAddZeroCommitment() public { - vm.expectRevert("cannot commit zero randomness"); - random.testRevealAndCommit(RANDONMESS, commitmentFor(0x00), ACCOUNT); - } - - function test_CanAddInitialCommitment() public { - random.testRevealAndCommit(RANDONMESS, commitmentFor(0x01), ACCOUNT); - } - - function test_CanRevealInitialCommitment() public { - vm.roll(2); - random.testRevealAndCommit(RANDONMESS, commitmentFor(0x01), ACCOUNT); - vm.roll(block.number + 1); - random.testRevealAndCommit(bytes32(uint256(0x01)), commitmentFor(0x02), ACCOUNT); - - bytes32 lastRandomness = random.getBlockRandomness(block.number - 1); - bytes32 expected = keccak256(abi.encodePacked(lastRandomness, bytes32(uint256(0x01)))); - - assertEq(random.getBlockRandomness(block.number), expected); - } -} diff --git a/packages/protocol/test-sol/stability/SortedOracles.t.sol b/packages/protocol/test-sol/stability/SortedOracles.t.sol deleted file mode 100644 index 54f83a532..000000000 --- a/packages/protocol/test-sol/stability/SortedOracles.t.sol +++ /dev/null @@ -1,586 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.5.13; -pragma experimental ABIEncoderV2; - -import { Test } from "celo-foundry/Test.sol"; -import { SortedOracles } from "../../contracts/stability/SortedOracles.sol"; -import "../../contracts/common/FixidityLib.sol"; -import "../../contracts/common/linkedlists/AddressSortedLinkedListWithMedian.sol"; -import "../../contracts/common/linkedlists/SortedLinkedListWithMedian.sol"; -import { Constants } from "../constants.sol"; - -contract SortedOraclesTest is Test, Constants { - using FixidityLib for FixidityLib.Fraction; - using AddressSortedLinkedListWithMedian for SortedLinkedListWithMedian.List; - - SortedOracles sortedOracle; - - address oracleAccount; - address aToken = 0x00000000000000000000000000000000DeaDBeef; - uint256 reportExpiry = 1 * 60 * 60; // 1 hour - - event OracleAdded(address indexed token, address indexed oracleAddress); - event OracleRemoved(address indexed token, address indexed oracleAddress); - event OracleReported( - address indexed token, - address indexed oracle, - uint256 timestamp, - uint256 value - ); - event OracleReportRemoved(address indexed token, address indexed oracle); - event MedianUpdated(address indexed token, uint256 value); - event ReportExpirySet(uint256 reportExpiry); - event TokenReportExpirySet(address token, uint256 reportExpiry); - - function setUp() public { - warp(0); - sortedOracle = new SortedOracles(true); - oracleAccount = actor("oracleAccount"); - sortedOracle.initialize(reportExpiry); - } - - function warp(uint256 timeToWarpTo) public { - vm.warp(YEAR + timeToWarpTo); - } -} - -contract Initialize is SortedOraclesTest { - function test_ownerSet() public { - assertEq(sortedOracle.owner(), address(this)); - } - - function test_ShouldSetReportExpiry() public { - assertEq(sortedOracle.reportExpirySeconds(), reportExpiry); - } - - function test_ShouldRevertWhenCalledAgain() public { - vm.expectRevert("contract already initialized"); - sortedOracle.initialize(reportExpiry); - } -} - -contract SetReportExpiry is SortedOraclesTest { - function test_ShouldSetReportExpiry() public { - uint256 newReportExpiry = reportExpiry * 2; - sortedOracle.setReportExpiry(newReportExpiry); - assertEq(sortedOracle.reportExpirySeconds(), newReportExpiry); - } - - function test_ShouldEmitReportExpirySetEvent() public { - uint256 newReportExpiry = reportExpiry * 2; - vm.expectEmit(true, true, true, true); - emit ReportExpirySet(newReportExpiry); - sortedOracle.setReportExpiry(newReportExpiry); - } - - function test_ShouldRevertWhenNotOwner() public { - vm.expectRevert("Ownable: caller is not the owner"); - vm.prank(oracleAccount); - sortedOracle.setReportExpiry(7200); - } -} - -contract SetTokenReportExpiry is SortedOraclesTest { - function test_ShouldSetTokenReportExpiry() public { - uint256 newReportExpiry = reportExpiry * 2; - sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); - assertEq(sortedOracle.tokenReportExpirySeconds(aToken), newReportExpiry); - } - - function test_ShouldEmitTokenReportExpirySetEvent() public { - uint256 newReportExpiry = reportExpiry * 2; - vm.expectEmit(true, true, true, true); - emit TokenReportExpirySet(aToken, newReportExpiry); - sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); - } - - function test_ShouldRevertWhenNotOwner() public { - vm.expectRevert("Ownable: caller is not the owner"); - vm.prank(oracleAccount); - sortedOracle.setTokenReportExpiry(aToken, 7200); - } -} - -contract AddOracle is SortedOraclesTest { - function test_ShouldAddOracle() public { - sortedOracle.addOracle(aToken, oracleAccount); - assertEq(sortedOracle.isOracle(aToken, oracleAccount), true); - } - - function test_ShouldEmitOracleAddedEvent() public { - vm.expectEmit(true, true, true, true); - emit OracleAdded(aToken, oracleAccount); - sortedOracle.addOracle(aToken, oracleAccount); - } - - function test_ShouldRevertWhenNotOwner() public { - vm.expectRevert("Ownable: caller is not the owner"); - vm.prank(oracleAccount); - sortedOracle.addOracle(aToken, oracleAccount); - } - - function test_ShouldRevertWhenAlreadyOracle() public { - sortedOracle.addOracle(aToken, oracleAccount); - vm.expectRevert("oracle addr is not an oracle for token addr"); - sortedOracle.addOracle(aToken, oracleAccount); - } - - function test_ShouldRevertWhenOracleIsZeroAddress() public { - vm.expectRevert("oracle addr was null"); - sortedOracle.addOracle(aToken, address(0)); - } - - function test_ShouldRevertWhenTokenIsZeroAddress() public { - vm.expectRevert("token addr was null"); - sortedOracle.addOracle(address(0), oracleAccount); - } -} - -contract GetTokenReportExpirySeconds is SortedOraclesTest { - function test_ShouldGetTokenReportExpirySeconds_WhenNoTokenLevelExpiryIsSet() public { - assertEq(sortedOracle.getTokenReportExpirySeconds(aToken), reportExpiry); - } - - function test_ShouldGetTokenReportExpirySeconds_WhenTokenLevelExpiryIsSet() public { - uint256 newReportExpiry = reportExpiry * 2; - sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); - assertEq(sortedOracle.getTokenReportExpirySeconds(aToken), newReportExpiry); - } -} - -contract RemoveExpiredReports is SortedOraclesTest { - function setUp() public { - super.setUp(); - sortedOracle.addOracle(aToken, oracleAccount); - } - - function test_ShouldRevertWhenNoReportExists() public { - vm.expectRevert("token addr null or trying to remove too many reports"); - sortedOracle.removeExpiredReports(aToken, 1); - } - - function test_ShouldRevertWhenReportIsNotExpired() public { - vm.prank(oracleAccount); - sortedOracle.report(aToken, FIXED1, address(0), address(0)); - vm.expectRevert("token addr null or trying to remove too many reports"); - sortedOracle.removeExpiredReports(aToken, 1); - } - - function helper_AddMultipleReports(uint256 numReports) public { - warp(reportExpiry / 2); - for (uint256 i = 0; i < numReports; i++) { - address oracle = actor(string(abi.encode("oracle", i))); - sortedOracle.addOracle(aToken, oracle); - vm.prank(oracle); - sortedOracle.report( - aToken, - FixidityLib.newFixedFraction(2, 1).unwrap(), - oracleAccount, - address(0) - ); - } - } - - function test_ShouldDoNothingWhenOldestReportIsNotExpired_WhenMultipleReportsHaveBeenMade() - public - { - vm.prank(oracleAccount); - sortedOracle.report(aToken, FIXED1, address(0), address(0)); - helper_AddMultipleReports(4); - sortedOracle.removeExpiredReports(aToken, 3); - assertEq(sortedOracle.numTimestamps(aToken), 5); - } - - function test_ShouldRemoveKAndStopWhenKIsLessThanNReportsAreExpired_WhenMultipleReportsHaveBeenMade() - public - { - vm.prank(oracleAccount); - sortedOracle.report(aToken, FIXED1, address(0), address(0)); - helper_AddMultipleReports(4); - warp(reportExpiry + 1); - sortedOracle.removeExpiredReports(aToken, 3); - assertEq(sortedOracle.numTimestamps(aToken), 4); - } - - function test_ShouldRevertWhenNGreaterOrEqualToNumTimestamps() public { - vm.prank(oracleAccount); - sortedOracle.report(aToken, FIXED1, address(0), address(0)); - helper_AddMultipleReports(4); - vm.expectRevert("token addr null or trying to remove too many reports"); - sortedOracle.removeExpiredReports(aToken, 5); - } - - function test_ShouldRemoveNWhenNIsLesserThanNumTimestamps_WhenMultipleReportsHaveBeenMade() - public - { - vm.prank(oracleAccount); - sortedOracle.report(aToken, FIXED1, address(0), address(0)); - helper_AddMultipleReports(4); - warp(2 * reportExpiry); - sortedOracle.removeExpiredReports(aToken, 3); - assertEq(sortedOracle.numTimestamps(aToken), 2); - } -} - -contract IsOldestReportExpired is SortedOraclesTest { - function setUp() public { - super.setUp(); - sortedOracle.addOracle(aToken, oracleAccount); - } - - function test_ShouldReturnTrueWhenNoReportExists() public { - (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); - assertEq(expired, true); - } - - function test_ShouldReturnTrueWhenOldestReportIsExpired() public { - vm.prank(oracleAccount); - sortedOracle.report(aToken, FIXED1, address(0), address(0)); - warp(reportExpiry + 1); - (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); - assertEq(expired, true); - } - - function test_ShouldReturnFalseWhenOldestReportIsNotExpired_WhenUsingDefaultExpiry() public { - vm.prank(oracleAccount); - sortedOracle.report(aToken, FIXED1, address(0), address(0)); - warp(reportExpiry - 1); - (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); - assertEq(expired, false); - } - - function test_ShouldNotExpire_WhenNoTimeHasPassed_WhenPerTokenExpiryIsSetToHigherThanDefault() - public - { - uint256 newReportExpiry = reportExpiry * 2; - vm.prank(oracleAccount); - sortedOracle.report(aToken, FIXED1, address(0), address(0)); - sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); - (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); - assertEq(expired, false); - } - - function test_ShouldExpire_WhenTokenExpiryTimeHasPassedAndPerTokenExpiryIsSetToHigherThanDefault() - public - { - uint256 newReportExpiry = reportExpiry * 2; - vm.prank(oracleAccount); - sortedOracle.report(aToken, FIXED1, address(0), address(0)); - sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); - warp(newReportExpiry + 1); - (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); - assertEq(expired, true); - } - - function test_ShouldNotExpire_WhenDefaultExpiryHasPassedAndPerTokenExpiryIsSetToHigherThanDefault() - public - { - uint256 newReportExpiry = reportExpiry * 2; - vm.prank(oracleAccount); - sortedOracle.report(aToken, FIXED1, address(0), address(0)); - sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); - warp(reportExpiry + 1); - (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); - assertEq(expired, false); - } - - function test_ShouldNotExpire_WhenNoTimeHasPassedAndPerTokenExpiryIsSetToLowerThanDefault() - public - { - uint256 newReportExpiry = reportExpiry / 2; - vm.prank(oracleAccount); - sortedOracle.report(aToken, FIXED1, address(0), address(0)); - sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); - (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); - assertEq(expired, false); - } - - function test_ShouldExpire_WhenDefaultExpiryHasPassedAndPerTokenExpiryIsSetToLowerThanDefault() - public - { - uint256 newReportExpiry = reportExpiry / 2; - vm.prank(oracleAccount); - sortedOracle.report(aToken, FIXED1, address(0), address(0)); - sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); - warp(reportExpiry + 1); - (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); - assertEq(expired, true); - } - - function test_ShouldExpire_WhenTokenExpiryHasPassedAndPerTokenExpiryIsSetToLowerThanDefault() - public - { - uint256 newReportExpiry = reportExpiry / 2; - vm.prank(oracleAccount); - sortedOracle.report(aToken, FIXED1, address(0), address(0)); - sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); - warp(newReportExpiry + 1); - (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); - assertEq(expired, true); - } -} - -contract RemoveOracle is SortedOraclesTest { - address oracleAccount2 = actor("oracleAccount2"); - - function setUp() public { - super.setUp(); - sortedOracle.addOracle(aToken, oracleAccount); - } - - function test_ShouldRemoveOracle() public { - sortedOracle.removeOracle(aToken, oracleAccount, 0); - assertEq(sortedOracle.isOracle(aToken, oracleAccount), false); - } - - function helper_WhenThereIsMoreThanOneReportMade() public { - sortedOracle.addOracle(aToken, oracleAccount2); - vm.prank(oracleAccount); - sortedOracle.report(aToken, FIXED1, address(0), address(0)); - vm.prank(oracleAccount2); - sortedOracle.report( - aToken, - FixidityLib.newFixedFraction(5, 1).unwrap(), - oracleAccount, - address(0) - ); - } - - function test_ShouldDecreaseTheNumberOfRates_WhenThereIsMoreThanOneReportMade() public { - helper_WhenThereIsMoreThanOneReportMade(); - sortedOracle.removeOracle(aToken, oracleAccount, 0); - assertEq(sortedOracle.numRates(aToken), 1); - } - - function test_ShouldDecreaseTheNumberOfTimestamps_WhenThereIsMoreThanOneReportMade() public { - helper_WhenThereIsMoreThanOneReportMade(); - sortedOracle.removeOracle(aToken, oracleAccount, 0); - assertEq(sortedOracle.numTimestamps(aToken), 1); - } - - function test_ShouldEmitOracleRemoved_WhenTHereIsMOreThanOneReportMade() public { - helper_WhenThereIsMoreThanOneReportMade(); - vm.expectEmit(true, true, true, true); - emit OracleRemoved(aToken, oracleAccount2); - sortedOracle.removeOracle(aToken, oracleAccount2, 1); - } - - function test_ShouldEmitOracleReportRemoved_WhenTHereIsMOreThanOneReportMade() public { - helper_WhenThereIsMoreThanOneReportMade(); - - vm.expectEmit(true, true, true, true); - emit OracleReportRemoved(aToken, oracleAccount2); - sortedOracle.removeOracle(aToken, oracleAccount2, 1); - } - - function test_ShouldEmitMedianUpdatedEvents_WhenTHereIsMOreThanOneReportMade() public { - helper_WhenThereIsMoreThanOneReportMade(); - vm.expectEmit(true, true, true, true); - emit MedianUpdated(aToken, FIXED1); - sortedOracle.removeOracle(aToken, oracleAccount2, 1); - } - - function test_ShouldNotDecreaseTheNumberOfRates_WhenThereIsASingleReportLeft() public { - vm.prank(oracleAccount); - sortedOracle.report( - aToken, - FixidityLib.newFixedFraction(10, 1).unwrap(), - address(0), - address(0) - ); - sortedOracle.removeOracle(aToken, oracleAccount, 0); - assertEq(sortedOracle.numRates(aToken), 1); - } - - function test_ShouldNotResetTheMedianRate_WhenThereIsASingleReportLeft() public { - vm.prank(oracleAccount); - sortedOracle.report( - aToken, - FixidityLib.newFixedFraction(10, 1).unwrap(), - address(0), - address(0) - ); - (uint256 originalMedianRate, uint256 originalNumOfRates) = sortedOracle.medianRate(aToken); - - sortedOracle.removeOracle(aToken, oracleAccount, 0); - (uint256 newMedianRate, uint256 newNumOfRates) = sortedOracle.medianRate(aToken); - assertEq(originalMedianRate, newMedianRate); - assertEq(originalNumOfRates, newNumOfRates); - } - - function test_ShouldNotDecreaseTheNumberOfTimestamps_WhenThereIsASingleReportLeft() public { - vm.prank(oracleAccount); - sortedOracle.report( - aToken, - FixidityLib.newFixedFraction(10, 1).unwrap(), - address(0), - address(0) - ); - sortedOracle.removeOracle(aToken, oracleAccount, 0); - assertEq(sortedOracle.numTimestamps(aToken), 1); - } - - function test_ShouldNotResetTheMedianTimestamp_WhenThereIsASingleReportLeft() public { - vm.prank(oracleAccount); - sortedOracle.report( - aToken, - FixidityLib.newFixedFraction(10, 1).unwrap(), - address(0), - address(0) - ); - uint256 originalMedianTimestamp = sortedOracle.medianTimestamp(aToken); - - sortedOracle.removeOracle(aToken, oracleAccount, 0); - uint256 newMedianTimestamp = sortedOracle.medianTimestamp(aToken); - assertEq(originalMedianTimestamp, newMedianTimestamp); - } - - // TODO: add test for not emitting any of the remove events once we migrate to 0.8 - - function test_ShouldEmitOracleRemovedEvent() public { - vm.expectEmit(true, true, true, true); - emit OracleRemoved(aToken, oracleAccount); - sortedOracle.removeOracle(aToken, oracleAccount, 0); - } - - function test_ShouldRevertWhenWrongIndexIsProvided() public { - vm.expectRevert( - "token addr null or oracle addr null or index of token oracle not mapped to oracle addr" - ); - sortedOracle.removeOracle(aToken, oracleAccount, 1); - } - - function test_ShouldRevertWhenWrongAddressIsProvided() public { - vm.expectRevert( - "token addr null or oracle addr null or index of token oracle not mapped to oracle addr" - ); - sortedOracle.removeOracle(aToken, address(this), 0); - } - - function test_ShouldRevertWhenCalledByNonOwner() public { - vm.expectRevert("Ownable: caller is not the owner"); - vm.prank(oracleAccount); - sortedOracle.removeOracle(aToken, oracleAccount, 0); - } -} - -contract Report is SortedOraclesTest { - uint256 value = FixidityLib.newFixedFraction(10, 1).unwrap(); - uint256 newValue = FixidityLib.newFixedFraction(12, 1).unwrap(); - - address anotherOracle = actor("anotherOracle"); - uint256 oracleValue1 = FixidityLib.newFixedFraction(2, 1).unwrap(); - uint256 oracleValue2 = FixidityLib.newFixedFraction(3, 1).unwrap(); - uint256 anotherOracleValue = FIXED1; - - function setUp() public { - super.setUp(); - sortedOracle.addOracle(aToken, oracleAccount); - } - - function test_ShouldIncreaseTheNumberOfRates() public { - vm.prank(oracleAccount); - sortedOracle.report(aToken, value, address(0), address(0)); - assertEq(sortedOracle.numRates(aToken), 1); - } - - function test_ShouldSetTheMedianRate() public { - vm.prank(oracleAccount); - sortedOracle.report(aToken, value, address(0), address(0)); - (uint256 medianRate, uint256 denominator) = sortedOracle.medianRate(aToken); - assertEq(medianRate, value); - assertEq(denominator, FIXED1); - } - - function test_ShouldIncreaseTheNumberOfTimestamps() public { - vm.prank(oracleAccount); - sortedOracle.report(aToken, value, address(0), address(0)); - assertEq(sortedOracle.numTimestamps(aToken), 1); - } - - function test_ShouldEmitOracleReportedEvent() public { - vm.expectEmit(true, true, true, true); - emit OracleReported(aToken, oracleAccount, now, value); - vm.prank(oracleAccount); - sortedOracle.report(aToken, value, address(0), address(0)); - } - - function test_ShouldEmitMedianUpdatedEvent() public { - vm.expectEmit(true, true, true, true); - emit MedianUpdated(aToken, value); - vm.prank(oracleAccount); - sortedOracle.report(aToken, value, address(0), address(0)); - } - - function test_ShouldRevertWhenCalledByNonOracle() public { - vm.expectRevert("sender was not an oracle for token addr"); - sortedOracle.report(aToken, value, address(0), address(0)); - } - - function test_ShouldSetTheMedianRate_WhenThereIsTwoReportsFromSameOracle() public { - vm.prank(oracleAccount); - sortedOracle.report(aToken, value, address(0), address(0)); - (uint256 medianRateOriginal, uint256 denominatorOriginal) = sortedOracle.medianRate(aToken); - assertEq(medianRateOriginal, value); - assertEq(denominatorOriginal, FIXED1); - vm.prank(oracleAccount); - sortedOracle.report(aToken, newValue, address(0), address(0)); - (uint256 medianRate, uint256 denominator) = sortedOracle.medianRate(aToken); - assertEq(medianRate, newValue); - assertEq(denominator, FIXED1); - } - - function test_ShouldNotChangeTheNumberOfTotalReports_WhenThereIsTwoReportsFromSameOracle() - public - { - vm.prank(oracleAccount); - sortedOracle.report(aToken, value, address(0), address(0)); - vm.prank(oracleAccount); - sortedOracle.report(aToken, newValue, address(0), address(0)); - assertEq(sortedOracle.numRates(aToken), 1); - } - - function helper_WhenThereAreMultipleReportsTheMostRecentOneDoneByThisOracle() public { - sortedOracle.addOracle(aToken, anotherOracle); - vm.prank(anotherOracle); - sortedOracle.report(aToken, anotherOracleValue, address(0), address(0)); - warp(5); - vm.prank(oracleAccount); - sortedOracle.report(aToken, oracleValue1, anotherOracle, address(0)); - warp(10); - (, uint256[] memory rateValues, ) = sortedOracle.getRates(aToken); - assertEq(rateValues[0], oracleValue1); - assertEq(rateValues[1], anotherOracleValue); - - } - - function test_ShouldUpdateTheListOfRatesCorrectly_WhenThereAreMultipleReportsTheMostRecentOneIsDoneByThisOracle() - public - { - helper_WhenThereAreMultipleReportsTheMostRecentOneDoneByThisOracle(); - - vm.prank(oracleAccount); - sortedOracle.report(aToken, oracleValue2, anotherOracle, address(0)); - - (, uint256[] memory rateValues, ) = sortedOracle.getRates(aToken); - assertEq(rateValues[0], oracleValue2); - assertEq(rateValues[1], anotherOracleValue); - } - - function test_ShouldUpdateTheLAtestTimestamp_WhenThereAreMultipleReportsTheMostRecentOneDoneByThisOracle() - public - { - helper_WhenThereAreMultipleReportsTheMostRecentOneDoneByThisOracle(); - - (, uint256[] memory timestampValuesBefore, ) = sortedOracle.getTimestamps(aToken); - - vm.prank(oracleAccount); - sortedOracle.report(aToken, oracleValue2, anotherOracle, address(0)); - - (, uint256[] memory timestampValuesAfter, ) = sortedOracle.getTimestamps(aToken); - - assertGt(timestampValuesAfter[0], timestampValuesBefore[0]); - assertEq(timestampValuesBefore[1], timestampValuesAfter[1]); - } - -} diff --git a/packages/protocol/test-sol/utils.sol b/packages/protocol/test-sol/utils.sol deleted file mode 100644 index d7885dd33..000000000 --- a/packages/protocol/test-sol/utils.sol +++ /dev/null @@ -1,10 +0,0 @@ -pragma solidity ^0.5.13; - -import "celo-foundry/Test.sol"; - -contract Utils is Test { - function timeTravel(uint256 timeDelta) public { - vm.warp(block.timestamp + timeDelta); - } - -} diff --git a/packages/protocol/test-sol/utils/GetCode.sol b/packages/protocol/test-sol/utils/GetCode.sol deleted file mode 100644 index bea82cc06..000000000 --- a/packages/protocol/test-sol/utils/GetCode.sol +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.4.16 <0.9.0; - -library GetCode { - function at(address _addr) public view returns (bytes memory o_code) { - assembly { - // retrieve the size of the code - let size := extcodesize(_addr) - // allocate output byte array - // by using o_code = new bytes(size) - o_code := mload(0x40) - // new "memory end" including padding - mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f)))) - // store length in memory - mstore(o_code, size) - // actually retrieve the code, this needs assembly - extcodecopy(_addr, add(o_code, 0x20), 0, size) - } - } -} diff --git a/packages/protocol/test-sol/utils/WithRegistry.sol b/packages/protocol/test-sol/utils/WithRegistry.sol deleted file mode 100644 index 006acfe8b..000000000 --- a/packages/protocol/test-sol/utils/WithRegistry.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.5.13; - -import "celo-foundry/Test.sol"; -import "contracts/common/Registry.sol"; -import "./GetCode.sol"; - -contract WithRegistry is Test { - address constant registryAddress = 0x000000000000000000000000000000000000ce10; - IRegistry public constant registry = IRegistry(registryAddress); - - constructor() public { - vm.etch(registryAddress, GetCode.at(address(new Registry(true)))); - vm.label(registryAddress, "Registry"); - vm.prank(actor("deployer")); - Registry(registryAddress).initialize(); - } -} diff --git a/packages/protocol/test/common/feecurrencywhitelist.ts b/packages/protocol/test/common/feecurrencywhitelist.ts deleted file mode 100644 index 6da1a5cf7..000000000 --- a/packages/protocol/test/common/feecurrencywhitelist.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { assertTransactionRevertWithReason } from '@celo/protocol/lib/test-utils' -import { FeeCurrencyWhitelistContract, FeeCurrencyWhitelistInstance } from 'types' - -const FeeCurrencyWhitelist: FeeCurrencyWhitelistContract = artifacts.require('FeeCurrencyWhitelist') - -contract('FeeCurrencyWhitelist', (accounts: string[]) => { - let feeCurrencyWhitelist: FeeCurrencyWhitelistInstance - - const aTokenAddress = '0x000000000000000000000000000000000000ce10' - - const nonOwner = accounts[1] - - beforeEach(async () => { - feeCurrencyWhitelist = await FeeCurrencyWhitelist.new(true) - await feeCurrencyWhitelist.initialize() - }) - - describe('#initialize()', () => { - it('should have set the owner', async () => { - const owner: string = await feeCurrencyWhitelist.owner() - assert.equal(owner, accounts[0]) - }) - - it('should not be callable again', async () => { - await assertTransactionRevertWithReason( - feeCurrencyWhitelist.initialize(), - 'contract already initialized' - ) - }) - }) - - describe('#addToken()', () => { - it('should allow the owner to add a token', async () => { - await feeCurrencyWhitelist.addToken(aTokenAddress) - const tokens = await feeCurrencyWhitelist.getWhitelist() - assert.sameMembers(tokens, [aTokenAddress]) - }) - - it('should not allow a non-owner to add a token', async () => { - await assertTransactionRevertWithReason( - feeCurrencyWhitelist.addToken(aTokenAddress, { from: nonOwner }), - 'Ownable: caller is not the owner' - ) - }) - }) - - describe('Removing', () => { - beforeEach(async () => { - await feeCurrencyWhitelist.addToken(aTokenAddress) - await feeCurrencyWhitelist.addToken(accounts[0]) - await feeCurrencyWhitelist.addToken(accounts[1]) - }) - - describe('#removeToken()', () => { - it('Removes from a big list', async () => { - await feeCurrencyWhitelist.removeToken(accounts[0], 1) - assert.sameMembers(await feeCurrencyWhitelist.getWhitelist(), [aTokenAddress, accounts[1]]) - }) - - it("Doesn't remove if the index is wrong", async () => { - await assertTransactionRevertWithReason( - feeCurrencyWhitelist.removeToken(accounts[0], 0), - 'Index does not match.' - ) - }) - - it('should not allow a non-owner to remove Mento token', async () => { - await assertTransactionRevertWithReason( - feeCurrencyWhitelist.removeToken(accounts[0], 0, { from: nonOwner }), - 'Ownable: caller is not the owner.' - ) - }) - }) - }) -}) diff --git a/packages/protocol/test/common/feehandler.ts b/packages/protocol/test/common/feehandler.ts deleted file mode 100644 index 4c2f93119..000000000 --- a/packages/protocol/test/common/feehandler.ts +++ /dev/null @@ -1,886 +0,0 @@ -// TODO remove magic numbers -// tslint:disable: ordered-imports -// TODO either pretiffy is not fixing this or the linter is broken -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { - assertEqualBN, - assertGtBN, - assertTransactionRevertWithReason, - assertTransactionRevertWithoutReason, - expectBigNumberInRange, - timeTravel, -} from '@celo/protocol/lib/test-utils' -import { fixed1, toFixed } from '@celo/utils/lib/fixidity' -import BigNumber from 'bignumber.js' -import { - FeeCurrencyWhitelistContract, - FeeCurrencyWhitelistInstance, - FeeHandlerContract, - FeeHandlerInstance, - FreezerContract, - FreezerInstance, - GoldTokenContract, - GoldTokenInstance, - MentoFeeHandlerSellerContract, - MentoFeeHandlerSellerInstance, - MockERC20Contract, - MockERC20Instance, - MockReserveContract, - MockReserveInstance, - MockSortedOraclesContract, - MockSortedOraclesInstance, - MockUniswapV2FactoryContract, - MockUniswapV2FactoryInstance, - MockUniswapV2Router02Contract, - MockUniswapV2Router02Instance, - RegistryContract, - RegistryInstance, - UniswapFeeHandlerSellerContract, - UniswapFeeHandlerSellerInstance, -} from 'types' - -import { - ExchangeContract, - ExchangeInstance, - StableTokenContract, - StableTokenEURContract, - StableTokenEURInstance, - StableTokenInstance, -} from 'types/mento' - -import { MENTO_PACKAGE } from '@celo/protocol/contractPackages' -import { makeTruffleContractForMigration } from '@celo/protocol/lib/web3-utils' -import { SECONDS_IN_A_WEEK, ZERO_ADDRESS } from '../constants' - -const goldAmountForRate = new BigNumber('1000000000000000000000000') -const stableAmountForRate = new BigNumber(2).times(goldAmountForRate) -const spread = toFixed(3 / 1000) -const reserveFraction = toFixed(5 / 100) -const maxSlippage = toFixed(1 / 100) -const initialReserveBalance = new BigNumber('10000000000000000000000') - -const FeeHandler: FeeHandlerContract = artifacts.require('FeeHandler') -const Registry: RegistryContract = artifacts.require('Registry') -const GoldToken: GoldTokenContract = artifacts.require('GoldToken') -const MockSortedOracles: MockSortedOraclesContract = artifacts.require('MockSortedOracles') -const MockReserve: MockReserveContract = artifacts.require('MockReserve') - -const Freezer: FreezerContract = artifacts.require('Freezer') -const ERC20: MockERC20Contract = artifacts.require('MockERC20') - -const UniswapRouter: MockUniswapV2Router02Contract = artifacts.require('MockUniswapV2Router02') -const UniswapV2Factory: MockUniswapV2FactoryContract = artifacts.require('MockUniswapV2Factory') - -const FeeCurrencyWhitelist: FeeCurrencyWhitelistContract = artifacts.require('FeeCurrencyWhitelist') - -const MentoFeeHandlerSeller: MentoFeeHandlerSellerContract = - artifacts.require('MentoFeeHandlerSeller') - -const UniswapFeeHandlerSeller: UniswapFeeHandlerSellerContract = - artifacts.require('UniswapFeeHandlerSeller') - -// Mento contracts -const Exchange: ExchangeContract = makeTruffleContractForMigration('Exchange', MENTO_PACKAGE, web3) -const StableToken: StableTokenContract = makeTruffleContractForMigration( - 'StableToken', - MENTO_PACKAGE, - web3 -) -const StableTokenEUR: StableTokenEURContract = makeTruffleContractForMigration( - 'StableTokenEUR', - MENTO_PACKAGE, - web3 -) - -const EXAMPLE_BENEFICIARY_ADDRESS = '0x2A486910DBC72cACcbb8d0e1439C96b03B2A4699' - -contract('FeeHandler', (accounts: string[]) => { - let feeHandler: FeeHandlerInstance - let exchange: ExchangeInstance - let exchange2: ExchangeInstance - let registry: RegistryInstance - let stableToken: StableTokenInstance - let stableToken2: StableTokenEURInstance - let goldToken: GoldTokenInstance - let mockSortedOracles: MockSortedOraclesInstance - let mockReserve: MockReserveInstance - let freezer: FreezerInstance - let mentoSeller: MentoFeeHandlerSellerInstance - let uniswapFeeHandlerSeller: UniswapFeeHandlerSellerInstance - let tokenA: MockERC20Instance - - let uniswapFactory: MockUniswapV2FactoryInstance - let uniswapFactory2: MockUniswapV2FactoryInstance - let uniswap: MockUniswapV2Router02Instance - let uniswap2: MockUniswapV2Router02Instance - let deadline - - let feeCurrencyWhitelist: FeeCurrencyWhitelistInstance - - const decimals = 18 - const updateFrequency = 60 * 60 - const minimumReports = 2 - - async function fundReserve() { - // Would have used goldToken here, but ran into issues of inability to transfer - // TODO: Remove in https://github.com/celo-org/celo-monorepo/issues/2000 - await web3.eth.sendTransaction({ - from: accounts[0], - to: mockReserve.address, - value: initialReserveBalance.toString(), - }) - } - - const user = accounts[1] - - beforeEach(async () => { - goldToken = await GoldToken.new(true) - mockReserve = await MockReserve.new() - stableToken = await StableToken.new(true) - stableToken2 = await StableTokenEUR.new(true) - registry = await Registry.new(true) - feeHandler = await FeeHandler.new(true) - freezer = await Freezer.new(true) - feeCurrencyWhitelist = await FeeCurrencyWhitelist.new(true) - mentoSeller = await MentoFeeHandlerSeller.new(true) - uniswapFeeHandlerSeller = await UniswapFeeHandlerSeller.new(true) - - tokenA = await ERC20.new() - await feeCurrencyWhitelist.initialize() - - await registry.setAddressFor( - CeloContractName.FeeCurrencyWhitelist, - feeCurrencyWhitelist.address - ) - await registry.setAddressFor(CeloContractName.Freezer, freezer.address) - - await registry.setAddressFor(CeloContractName.GoldToken, goldToken.address) - await registry.setAddressFor(CeloContractName.Reserve, mockReserve.address) - await mockReserve.setGoldToken(goldToken.address) - await mockReserve.addToken(stableToken.address) - await mockReserve.addToken(stableToken2.address) - - await mentoSeller.initialize(registry.address, [], []) - - await goldToken.initialize(registry.address) - // TODO: use MockStableToken for this - await stableToken.initialize( - 'Celo Dollar', - 'cUSD', - decimals, - registry.address, - fixed1, - SECONDS_IN_A_WEEK, - [], - [], - CeloContractName.Exchange // USD - ) - - await stableToken2.initialize( - 'Celo Euro', - 'cEUR', - decimals, - registry.address, - fixed1, - SECONDS_IN_A_WEEK, - [], - [], - CeloContractName.ExchangeEUR // USD - ) - - mockSortedOracles = await MockSortedOracles.new() - await registry.setAddressFor(CeloContractName.SortedOracles, mockSortedOracles.address) - - await mockSortedOracles.setMedianRate(stableToken.address, stableAmountForRate) - await mockSortedOracles.setMedianTimestampToNow(stableToken.address) - await mockSortedOracles.setNumRates(stableToken.address, 2) - // StableToken 2 - await mockSortedOracles.setMedianRate(stableToken2.address, stableAmountForRate) - await mockSortedOracles.setMedianTimestampToNow(stableToken2.address) - await mockSortedOracles.setNumRates(stableToken2.address, 2) - - await fundReserve() - - exchange = await Exchange.new(true) - await exchange.initialize( - registry.address, - CeloContractName.StableToken, - spread, - reserveFraction, - updateFrequency, - minimumReports - ) - - exchange2 = await Exchange.new(true) - await exchange2.initialize( - registry.address, - CeloContractName.StableTokenEUR, - spread, - reserveFraction, - updateFrequency, - minimumReports - ) - - await registry.setAddressFor(CeloContractName.StableToken, stableToken.address) - await registry.setAddressFor(CeloContractName.Exchange, exchange.address) - - await registry.setAddressFor(CeloContractName.StableTokenEUR, stableToken2.address) - await registry.setAddressFor(CeloContractName.ExchangeEUR, exchange2.address) - - await exchange.activateStable() - await exchange2.activateStable() - - await feeHandler.initialize(registry.address, EXAMPLE_BENEFICIARY_ADDRESS, 0, [], [], [], []) - }) - - describe('#setBurnFraction()', () => { - it('updates burn fraction correctly', async () => { - await feeHandler.setBurnFraction(toFixed(80 / 100)) - assertEqualBN(await feeHandler.burnFraction(), toFixed(80 / 100)) - }) - - it('only allows owner to change the burn fraction', async () => { - await assertTransactionRevertWithReason( - feeHandler.setBurnFraction(toFixed(80 / 100), { from: user }), - 'Ownable: caller is not the owner.' - ) - }) - - it("doesn't allow numbers bigger than one", async () => { - await assertTransactionRevertWithReason( - feeHandler.setBurnFraction(toFixed(80 / 100), { from: user }), - 'Ownable: caller is not the owner.' - ) - }) - }) - - describe('#setHandler()', () => { - it('sets handler', async () => { - await feeHandler.setHandler(stableToken.address, mentoSeller.address) - assert(await feeHandler.getTokenHandler(stableToken.address), mentoSeller.address) - }) - - it('Only owner can set handler', async () => { - await assertTransactionRevertWithReason( - feeHandler.setHandler(stableToken.address, mentoSeller.address, { from: user }), - 'Ownable: caller is not the owner' - ) - }) - }) - - describe('#addToken()', () => { - it('adds it to the list', async () => { - await feeHandler.addToken(stableToken.address, mentoSeller.address) - assert.sameMembers(await feeHandler.getActiveTokens(), [stableToken.address]) - const handlerAddress = await feeHandler.getTokenHandler(stableToken.address) - assert(await feeHandler.getTokenActive(stableToken.address), 'status added as active') - assert.sameMembers(await feeHandler.getActiveTokens(), [stableToken.address]) - assert( - handlerAddress.toLocaleLowerCase() === mentoSeller.address.toLowerCase(), - 'handler is correct' - ) - }) - - it('Only owner can add token', async () => { - await assertTransactionRevertWithReason( - feeHandler.addToken(stableToken.address, mentoSeller.address, { from: user }), - 'Ownable: caller is not the owner' - ) - }) - }) - - describe('#removeToken()', () => { - it('Removes form the list', async () => { - await feeHandler.addToken(stableToken.address, mentoSeller.address) - await feeHandler.removeToken(stableToken.address) - assert( - (await feeHandler.getTokenActive(stableToken.address)) === false, - 'status is not active' - ) - assert.sameMembers(await feeHandler.getActiveTokens(), []) - assert((await feeHandler.getTokenHandler(stableToken.address)) === ZERO_ADDRESS) - }) - - it('Only owner can remove token', async () => { - await assertTransactionRevertWithReason( - feeHandler.removeToken(stableToken.address, { from: user }), - 'Ownable: caller is not the owner.' - ) - }) - }) - - describe('#deactivateToken() and activateToken()', () => { - it('Removes form the list and adds it back', async () => { - await feeHandler.addToken(stableToken.address, mentoSeller.address) - await feeHandler.deactivateToken(stableToken.address) - assert( - (await feeHandler.getTokenActive(stableToken.address)) === false, - 'status is not active' - ) - - assert.sameMembers(await feeHandler.getActiveTokens(), []) - - await feeHandler.activateToken(stableToken.address) - assert((await feeHandler.getTokenActive(stableToken.address)) === true, 'status is active') - - assert.sameMembers(await feeHandler.getActiveTokens(), [stableToken.address]) - }) - - it('Only owner can deactivate token', async () => { - await assertTransactionRevertWithReason( - feeHandler.deactivateToken(stableToken.address, { from: user }), - 'Ownable: caller is not the owner.' - ) - }) - }) - - describe('#setFeeBeneficiary()', () => { - it('updates address correctly', async () => { - await feeHandler.setFeeBeneficiary(EXAMPLE_BENEFICIARY_ADDRESS) - assert(await feeHandler.feeBeneficiary(), EXAMPLE_BENEFICIARY_ADDRESS) - }) - - it('only allows owner to change the burn fraction', async () => { - await assertTransactionRevertWithReason( - feeHandler.setBurnFraction(EXAMPLE_BENEFICIARY_ADDRESS, { from: user }), - 'Ownable: caller is not the owner.' - ) - }) - }) - - describe('#distribute()', () => { - beforeEach(async () => { - await feeHandler.setFeeBeneficiary(EXAMPLE_BENEFICIARY_ADDRESS) - }) - - it("Can't distribute when not active", async () => { - await assertTransactionRevertWithReason( - feeHandler.distribute(stableToken.address), - 'Handler has to be set to sell token' - ) - }) - - describe('When token is active', () => { - beforeEach(async () => { - await feeHandler.addToken(stableToken.address, mentoSeller.address) - await feeHandler.activateToken(stableToken.address) - }) - - it("Can't distribute when frozen", async () => { - await freezer.freeze(feeHandler.address) - await assertTransactionRevertWithReason( - feeHandler.distribute(stableToken.address), - "can't call when contract is frozen" - ) - }) - - it("doesn't distribute when balance is zero", async () => { - assertEqualBN(await stableToken.balanceOf(feeHandler.address), 0) - const res = await feeHandler.distribute(stableToken.address) - assert(res.logs.length === 0, 'No transfer should be done (nor event emitted)') - }) - - describe('#distribute() with balance', () => { - beforeEach(async () => { - const goldTokenAmount = new BigNumber(1e18) - - await goldToken.approve(exchange.address, goldTokenAmount, { from: user }) - await exchange.sell(goldTokenAmount, 0, true, { from: user }) - await feeHandler.setMaxSplippage(stableToken.address, toFixed(1 / 50)) - await feeHandler.addToken(stableToken.address, mentoSeller.address) - await feeHandler.setBurnFraction(toFixed(80 / 100)) - await stableToken.transfer(feeHandler.address, new BigNumber('1e18'), { - from: user, - }) - await feeHandler.setMaxSplippage(stableToken.address, toFixed(1)) - - await feeHandler.sell(stableToken.address) - }) - - it('distributes after a burn', async () => { - await feeHandler.distribute(stableToken.address) - assertEqualBN(await stableToken.balanceOf(feeHandler.address), 0) - assertEqualBN( - await stableToken.balanceOf(EXAMPLE_BENEFICIARY_ADDRESS), - new BigNumber('0.2e18') - ) - }) - }) - }) - }) - - describe('#burnCelo()', () => { - beforeEach(async () => { - await feeHandler.setBurnFraction(toFixed(80 / 100)) - await goldToken.transfer(feeHandler.address, new BigNumber('1e18'), { - from: user, - }) - - await feeHandler.setFeeBeneficiary(EXAMPLE_BENEFICIARY_ADDRESS) - await feeHandler.addToken(stableToken.address, mentoSeller.address) - await feeHandler.activateToken(stableToken.address) - await feeHandler.activateToken(goldToken.address) - }) - - it('distribute correctly', async () => { - await feeHandler.burnCelo() - assertEqualBN(await goldToken.balanceOf(feeHandler.address), new BigNumber('0.2e18')) - assertEqualBN(await goldToken.getBurnedAmount(), new BigNumber('0.8e18')) - }) - - it("Doesn't burn what it's pending distribution", async () => { - const previousBurn = await goldToken.getBurnedAmount() // status is not reset inbetween tests, so keep track of the previus burn - - await feeHandler.burnCelo() - - assertEqualBN( - new BigNumber(await goldToken.getBurnedAmount()), - new BigNumber('0.8e18').plus(previousBurn) - ) - - await feeHandler.burnCelo() - assertEqualBN(await goldToken.balanceOf(feeHandler.address), new BigNumber('0.2e18')) - assertEqualBN(await goldToken.getBurnedAmount(), new BigNumber('0.8e18').plus(previousBurn)) - }) - - it('distributes correctly after a burn', async () => { - await feeHandler.burnCelo() - await feeHandler.distribute(stableToken.address) - assertEqualBN(await goldToken.balanceOf(feeHandler.address), new BigNumber('0.2e18')) - await feeHandler.distribute(goldToken.address) - assertEqualBN(await goldToken.balanceOf(EXAMPLE_BENEFICIARY_ADDRESS), new BigNumber('0.2e18')) - }) - }) - - describe('#sell()', () => { - beforeEach(async () => { - await feeHandler.setBurnFraction(toFixed(80 / 100)) - }) - - it("Can't sell when frozen", async () => { - await freezer.freeze(feeHandler.address) - await assertTransactionRevertWithoutReason( - feeHandler.sell(stableToken.address), - "can't call when contract is frozen." - ) - }) - - describe('Mento tokens', async () => { - beforeEach(async () => { - const goldTokenAmount = new BigNumber(1e18) - - await goldToken.approve(exchange.address, goldTokenAmount, { from: user }) - await exchange.sell(goldTokenAmount, 0, true, { from: user }) - await feeHandler.addToken(stableToken.address, mentoSeller.address) - await feeHandler.setMaxSplippage(stableToken.address, toFixed(1)) - }) - - it("doesn't sell when balance is low", async () => { - await stableToken.transfer(feeHandler.address, new BigNumber(await feeHandler.MIN_BURN()), { - from: user, - }) - - const balanceBefore = await stableToken.balanceOf(feeHandler.address) - - await feeHandler.sell(stableToken.address) - - assertEqualBN(await stableToken.balanceOf(feeHandler.address), balanceBefore) - }) - - it('reset burn limit after 24 hours', async () => { - await feeHandler.setDailySellLimit(stableToken.address, new BigNumber(1000)) - - await stableToken.transfer(feeHandler.address, new BigNumber(3000), { - from: user, - }) - - await feeHandler.sell(stableToken.address) - await timeTravel(3600 * 24, web3) - await feeHandler.sell(stableToken.address) - - assertEqualBN(await stableToken.balanceOf(feeHandler.address), new BigNumber(1000)) - }) - - it("doesn't burn when bigger than limit", async () => { - await feeHandler.setDailySellLimit(stableToken.address, new BigNumber(1000)) - - await stableToken.transfer(feeHandler.address, new BigNumber(3000), { - from: user, - }) - - await feeHandler.sell(stableToken.address) - - assertEqualBN(await stableToken.balanceOf(feeHandler.address), new BigNumber(2000)) - - // burning again shouldn't do anything - await feeHandler.sell(stableToken.address) - assertEqualBN(await stableToken.balanceOf(feeHandler.address), new BigNumber(2000)) - }) - - describe('load balance', async () => { - beforeEach(async () => { - await stableToken.transfer(feeHandler.address, new BigNumber('1e18'), { - from: user, - }) - }) - - it('burns with mento', async () => { - assertEqualBN(await feeHandler.getPastBurnForToken(stableToken.address), 0) - const burnedAmountStable = await stableToken.balanceOf(feeHandler.address) - await feeHandler.setMaxSplippage(stableToken.address, toFixed(1)) - await feeHandler.sell(stableToken.address) - assertEqualBN( - await feeHandler.getPastBurnForToken(stableToken.address), - new BigNumber(burnedAmountStable).multipliedBy('0.8') - ) - assertEqualBN(await stableToken.balanceOf(feeHandler.address), new BigNumber('0.2e18')) - assertEqualBN( - await feeHandler.getTokenToDistribute(stableToken.address), - new BigNumber('0.2e18') - ) - - expectBigNumberInRange( - new BigNumber(await feeHandler.celoToBeBurned()), - new BigNumber( - await exchange.getBuyTokenAmount( - new BigNumber(burnedAmountStable).multipliedBy('0.2'), - true - ) - ), - new BigNumber('100000000000000000') // 0.1 Celo - ) - }) - - it("Doesn't exchange when not enough reports", async () => { - await mentoSeller.setMinimumReports(tokenA.address, 2) - const balanceBefore = await stableToken.balanceOf(feeHandler.address) // TODO this balance is wrong - await feeHandler.setMaxSplippage(tokenA.address, maxSlippage) - await assertTransactionRevertWithReason( - feeHandler.sell(tokenA.address), - 'Handler has to be set to sell token.' - ) - assertEqualBN(await stableToken.balanceOf(feeHandler.address), balanceBefore) - }) - - it("Doesn't burn balance if it hasn't distributed", async () => { - await feeHandler.setMaxSplippage(stableToken.address, toFixed(1)) - await feeHandler.sell(stableToken.address) - const balanceFefore = await stableToken.balanceOf(feeHandler.address) - await feeHandler.sell(stableToken.address) - - assertEqualBN(balanceFefore, await stableToken.balanceOf(feeHandler.address)) - }) - }) - }) - - describe('Other tokens (non-Mento)', async () => { - beforeEach(async () => { - deadline = (await web3.eth.getBlock('latest')).timestamp + 100 - uniswapFactory = await UniswapV2Factory.new('0x0000000000000000000000000000000000000000') // feeSetter - // tslint:disable-next-line - console.log('Uniswap INIT CODE PAIR HASH:', await uniswapFactory.INIT_CODE_PAIR_HASH()) - - const initCodePairHash = await uniswapFactory.INIT_CODE_PAIR_HASH() - - uniswap = await UniswapRouter.new( - uniswapFactory.address, - '0x0000000000000000000000000000000000000000', - initCodePairHash - ) // _factory, _WETH - - uniswapFactory2 = await UniswapV2Factory.new('0x0000000000000000000000000000000000000000') // feeSetter - - uniswap2 = await UniswapRouter.new( - uniswapFactory2.address, - '0x0000000000000000000000000000000000000000', - initCodePairHash - ) // _factory, _WETH - - await feeCurrencyWhitelist.addToken(tokenA.address) - await uniswapFeeHandlerSeller.initialize(registry.address, [], []) - await uniswapFeeHandlerSeller.setRouter(tokenA.address, uniswap.address) - await tokenA.mint(feeHandler.address, new BigNumber(10e18)) - await tokenA.mint(user, new BigNumber(10e18)) - await goldToken.transfer(user, new BigNumber(10e18)) - const toTransfer = new BigNumber(5e18) - - await tokenA.approve(uniswap.address, toTransfer, { from: user }) - await goldToken.approve(uniswap.address, toTransfer, { from: user }) - - await uniswap.addLiquidity( - tokenA.address, - goldToken.address, - toTransfer, - toTransfer, - toTransfer, - toTransfer, - user, - deadline, - { from: user } - ) - - await feeHandler.addToken(tokenA.address, uniswapFeeHandlerSeller.address) - await feeHandler.setMaxSplippage(tokenA.address, toFixed(1)) - }) - - describe('Oracle check', async () => { - beforeEach(async () => { - await uniswapFeeHandlerSeller.setMinimumReports(tokenA.address, 1) - // tolerate high slippage, just to activate oracle check - await feeHandler.setMaxSplippage(tokenA.address, toFixed(99 / 100)) - await mockSortedOracles.setMedianRate( - tokenA.address, - new BigNumber(1).times(goldAmountForRate) - ) - }) - - it("Doesn't exchange when not enough reports", async () => { - await assertTransactionRevertWithReason( - feeHandler.sell(tokenA.address), - 'Number of reports for token not enough' - ) - assertEqualBN(await tokenA.balanceOf(feeHandler.address), new BigNumber(10e18)) - }) - - it('Works with check', async () => { - await mockSortedOracles.setNumRates(tokenA.address, 2) - await feeHandler.sell(tokenA.address) - assertEqualBN(await tokenA.balanceOf(feeHandler.address), new BigNumber('2e18')) - }) - - it('Fails when oracle slippage is high check', async () => { - await mockSortedOracles.setNumRates(tokenA.address, 2) - await feeHandler.setMaxSplippage(tokenA.address, toFixed(80 / 100)) - // The next tx is the one that should cause the revert, forcing a very - await mockSortedOracles.setMedianRate( - tokenA.address, - new BigNumber('300').times(goldAmountForRate) - ) - await assertTransactionRevertWithReason( - feeHandler.sell(tokenA.address), - 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT' - ) - }) - }) - - it('Uniswap trade test', async () => { - // Make sure our uniswap mock works - - const balanceAbefore = await tokenA.balanceOf(user) - const balanceBbefore = await goldToken.balanceOf(user) - - await tokenA.approve(uniswap.address, new BigNumber(1e18), { from: user }) - await uniswap.swapExactTokensForTokens( - new BigNumber(1e18), - 0, - [tokenA.address, goldToken.address], - user, - deadline, - { from: user } - ) - - assertGtBN(balanceAbefore, await tokenA.balanceOf(user)) - assertGtBN(await goldToken.balanceOf(user), balanceBbefore) - }) - - it('Sells non-Mento tokens', async () => { - // await tokenA.mint(feeHandler.address, new BigNumber(10e18)) - - // safety check, check that the balance is not empty before the burn - await assertGtBN(await tokenA.balanceOf(feeHandler.address), 0) - await feeHandler.sell(tokenA.address) - - // Burns only burn fraction, not all - assertEqualBN(await tokenA.balanceOf(feeHandler.address), new BigNumber('2e18')) - }) - - it("Doesn't exchange when slippage is too high", async () => { - await feeHandler.setMaxSplippage(tokenA.address, maxSlippage) - await assertTransactionRevertWithReason( - feeHandler.sell(tokenA.address), - 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT' - ) - assertEqualBN(await tokenA.balanceOf(feeHandler.address), new BigNumber(10e18)) - }) - - it('Tries to get the best rate with many exchanges', async () => { - await uniswapFeeHandlerSeller.setRouter(tokenA.address, uniswap2.address) - await tokenA.mint(user, new BigNumber(10e18)) - - // safety check, check that the balance is no empty before the burn - await assertGtBN(await tokenA.balanceOf(feeHandler.address), 0) - - const toTransfer = new BigNumber(10e18) // make uniswap2 bigger, so it should get used - - await tokenA.approve(uniswap2.address, toTransfer, { from: user }) - await goldToken.approve(uniswap2.address, toTransfer, { from: user }) - - await uniswap2.addLiquidity( - tokenA.address, - goldToken.address, - toTransfer, - toTransfer, - toTransfer, - toTransfer, - user, - deadline, - { from: user } - ) - - const quote1before = ( - await uniswap.getAmountsOut(new BigNumber(1e18), [tokenA.address, goldToken.address]) - )[1] - const quote2before = ( - await uniswap2.getAmountsOut(new BigNumber(1e18), [tokenA.address, goldToken.address]) - )[1] - - await feeHandler.sell(tokenA.address) - - // liquidity should have been taken of uniswap2, because it has better liquidity, and thus higher quote - // so the quote gets worse (smaller number) - - const quote1after = ( - await uniswap.getAmountsOut(new BigNumber(1e18), [tokenA.address, goldToken.address]) - )[1] - const quote2after = ( - await uniswap2.getAmountsOut(new BigNumber(1e18), [tokenA.address, goldToken.address]) - )[1] - - assertEqualBN(quote1before, quote1after) // uniswap 1 should be untouched - assertGtBN(quote2before, quote2after) - - assertEqualBN(await tokenA.balanceOf(feeHandler.address), new BigNumber('2e18')) // check that it burned - }) - }) - }) - - describe('#handle() (Mento tokens only)', () => { - beforeEach(async () => { - await goldToken.transfer(feeHandler.address, new BigNumber('1e18'), { - from: user, - }) - await feeHandler.setBurnFraction(toFixed(80 / 100)) - await feeHandler.setFeeBeneficiary(EXAMPLE_BENEFICIARY_ADDRESS) - }) - - it('should revert when token not added', async () => { - await assertTransactionRevertWithReason( - feeHandler.handle(stableToken.address), - 'Handler has to be set to sell token' - ) - }) - - describe('When token active', () => { - beforeEach(async () => { - await feeHandler.activateToken(goldToken.address) - }) - - it('handles Celo', async () => { - const pastBurn = await goldToken.getBurnedAmount() - const previusBeneficiaryBalance = await goldToken.balanceOf(EXAMPLE_BENEFICIARY_ADDRESS) - // basically it just does a burn - await feeHandler.handle(goldToken.address) - assertEqualBN(await goldToken.getBurnedAmount(), new BigNumber('0.8e18').plus(pastBurn)) - assertEqualBN( - await goldToken.balanceOf(EXAMPLE_BENEFICIARY_ADDRESS), - new BigNumber('0.2e18').plus(previusBeneficiaryBalance) - ) - }) - }) - }) - - describe('#handleAll()', () => { - beforeEach(async () => { - const goldTokenAmount = new BigNumber(1e18) - - await goldToken.approve(exchange.address, goldTokenAmount, { from: user }) - await goldToken.approve(exchange2.address, goldTokenAmount, { from: user }) - - await exchange.sell(goldTokenAmount, 0, true, { from: user }) - await exchange2.sell(goldTokenAmount, 0, true, { from: user }) - - await feeHandler.addToken(stableToken.address, mentoSeller.address) - await feeHandler.addToken(stableToken2.address, mentoSeller.address) - await feeHandler.setMaxSplippage(stableToken.address, toFixed(1)) - await feeHandler.setMaxSplippage(stableToken2.address, toFixed(1)) - - await feeHandler.setBurnFraction(toFixed(80 / 100)) - await feeHandler.setFeeBeneficiary(EXAMPLE_BENEFICIARY_ADDRESS) - }) - - it('burns with mento', async () => { - const previousBurn = await goldToken.getBurnedAmount() - await stableToken.transfer(feeHandler.address, new BigNumber('1e18'), { - from: user, - }) - await stableToken2.transfer(feeHandler.address, new BigNumber('1e18'), { - from: user, - }) - - assertEqualBN(await feeHandler.getPastBurnForToken(stableToken.address), 0) - const burnedAmountStable = await stableToken.balanceOf(feeHandler.address) - - await feeHandler.handleAll() - - assertEqualBN( - await feeHandler.getPastBurnForToken(stableToken.address), - new BigNumber(burnedAmountStable).multipliedBy('0.8') - ) - assertEqualBN( - await feeHandler.getPastBurnForToken(stableToken2.address), - new BigNumber(burnedAmountStable).multipliedBy('0.8') - ) - assertEqualBN( - await stableToken.balanceOf(EXAMPLE_BENEFICIARY_ADDRESS), - new BigNumber('0.2e18') - ) - assertEqualBN( - await stableToken2.balanceOf(EXAMPLE_BENEFICIARY_ADDRESS), - new BigNumber('0.2e18') - ) - // everything should have been burned - - assertEqualBN(await feeHandler.getTokenToDistribute(stableToken.address), 0) - assertEqualBN(await feeHandler.getTokenToDistribute(stableToken2.address), 0) - - // burn is non zero - assertGtBN(await goldToken.getBurnedAmount(), previousBurn) - }) - }) - - describe('#transfer()', () => { - beforeEach(async () => { - await tokenA.mint(feeHandler.address, new BigNumber(1e18)) - }) - - it('Only owner can take tokens out', async () => { - await assertTransactionRevertWithReason( - feeHandler.transfer(tokenA.address, user, new BigNumber(1e18), { from: user }), - 'Ownable: caller is not the owner.' - ) - }) - - it('Can take funds out', async () => { - await feeHandler.transfer(tokenA.address, user, new BigNumber(1e18)) - assertEqualBN(await tokenA.balanceOf(user), new BigNumber(1e18)) - }) - }) - - describe('#setDailySellLimit()', () => { - it('should only be called by owner', async () => { - await assertTransactionRevertWithReason( - feeHandler.setDailySellLimit(stableToken.address, goldAmountForRate, { from: user }), - 'Ownable: caller is not the owner.' - ) - }) - }) - - describe('#setMaxSplipagge()', () => { - it('should only be called by owner', async () => { - await assertTransactionRevertWithReason( - feeHandler.setMaxSplippage(stableToken.address, maxSlippage, { from: user }), - 'Ownable: caller is not the owner.' - ) - }) - }) -}) diff --git a/packages/protocol/test/common/feehandlerseller.ts b/packages/protocol/test/common/feehandlerseller.ts deleted file mode 100644 index f0f47aa6e..000000000 --- a/packages/protocol/test/common/feehandlerseller.ts +++ /dev/null @@ -1,95 +0,0 @@ -// /* tslint:disable */ - -// TODO remove magic numbers -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { assertEqualBN, assertTransactionRevertWithReason } from '@celo/protocol/lib/test-utils' -import BigNumber from 'bignumber.js' -import { - GoldTokenContract, - GoldTokenInstance, - MentoFeeHandlerSellerContract, - MentoFeeHandlerSellerInstance, - RegistryContract, - RegistryInstance, - UniswapFeeHandlerSellerContract, - UniswapFeeHandlerSellerInstance, -} from 'types' - -const MentoFeeHandlerSeller: MentoFeeHandlerSellerContract = - artifacts.require('MentoFeeHandlerSeller') - -const UniswapFeeHandlerSeller: UniswapFeeHandlerSellerContract = - artifacts.require('UniswapFeeHandlerSeller') - -const GoldToken: GoldTokenContract = artifacts.require('GoldToken') -const Registry: RegistryContract = artifacts.require('Registry') - -const oneCelo = new BigNumber('1e18') - -contract('FeeHandlerSeller', (accounts: string[]) => { - let uniswapFeeHandlerSeller: UniswapFeeHandlerSellerInstance - let mentoFeeHandlerSeller: MentoFeeHandlerSellerInstance - let goldToken: GoldTokenInstance - let registry: RegistryInstance - - let contractsToTest - const user = accounts[1] - - beforeEach(async () => { - registry = await Registry.new(true) - - goldToken = await GoldToken.new(true) - await goldToken.initialize(registry.address) - await registry.setAddressFor(CeloContractName.GoldToken, goldToken.address) - - uniswapFeeHandlerSeller = await UniswapFeeHandlerSeller.new(true) - mentoFeeHandlerSeller = await MentoFeeHandlerSeller.new(true) - contractsToTest = [mentoFeeHandlerSeller, uniswapFeeHandlerSeller] - for (const contract of contractsToTest) { - await contract.initialize(registry.address, [], []) - } - }) - - describe('#transfer()', () => { - it(`transfer works`, async () => { - for (const contract of contractsToTest) { - const receiver = web3.eth.accounts.create().address - assertEqualBN(await goldToken.balanceOf(receiver), new BigNumber(0)) - - await goldToken.transfer(contract.address, oneCelo) - await contract.transfer(goldToken.address, oneCelo, receiver) - assertEqualBN(await goldToken.balanceOf(receiver), oneCelo) - assertEqualBN(await goldToken.balanceOf(contract.address), new BigNumber(0)) - } - }) - - it('only owner can transfer', async () => { - const receiver = web3.eth.accounts.create().address - for (const contract of contractsToTest) { - await goldToken.transfer(contract.address, oneCelo) - await assertTransactionRevertWithReason( - contract.transfer(goldToken.address, oneCelo, receiver, { from: user }), - 'Ownable: caller is not the owner' - ) - } - }) - }) - - describe('#setMinimumReports()', () => { - it(`setMinimumReports works`, async () => { - for (const contract of contractsToTest) { - await contract.setMinimumReports(goldToken.address, 15) - assertEqualBN(await contract.minimumReports(goldToken.address), 15) - } - }) - - it('only owner can setMinimumReports', async () => { - for (const contract of contractsToTest) { - await assertTransactionRevertWithReason( - contract.setMinimumReports(goldToken.address, 1, { from: user }), - 'Ownable: caller is not the owner.' - ) - } - }) - }) -}) diff --git a/packages/protocol/test/common/gaspriceminimum.ts b/packages/protocol/test/common/gaspriceminimum.ts deleted file mode 100644 index 990e39607..000000000 --- a/packages/protocol/test/common/gaspriceminimum.ts +++ /dev/null @@ -1,275 +0,0 @@ -import { NULL_ADDRESS } from '@celo/base/lib/address' -import { - assertEqualBN, - assertLogMatches2, - assertTransactionRevertWithReason, -} from '@celo/protocol/lib/test-utils' -import { fromFixed, toFixed } from '@celo/utils/lib/fixidity' -import BigNumber from 'bignumber.js' -import { RegistryContract, RegistryInstance } from 'types' -import { GasPriceMinimumContract, GasPriceMinimumInstance } from 'types/08' -import { SOLIDITY_08_PACKAGE } from '../../contractPackages' -import { ArtifactsSingleton } from '../../lib/artifactsSingleton' - -const Registry: RegistryContract = artifacts.require('Registry') -const GasPriceMinimum: GasPriceMinimumContract = - ArtifactsSingleton.getInstance(SOLIDITY_08_PACKAGE).require('GasPriceMinimum') - -// @ts-ignore -// TODO(mcortesi): Use BN -GasPriceMinimum.numberFormat = 'BigNumber' - -contract('GasPriceMinimum', (accounts: string[]) => { - let gasPriceMinimum: GasPriceMinimumInstance - let registry: RegistryInstance - const nonOwner = accounts[1] - const gasPriceMinimumFloor = new BigNumber(100) - const initialGasPriceMinimum = gasPriceMinimumFloor - const targetDensity = toFixed(1 / 2) - const adjustmentSpeed = toFixed(1 / 2) - - beforeEach(async () => { - registry = await Registry.new(true) - gasPriceMinimum = await GasPriceMinimum.new(true) - - await gasPriceMinimum.initialize( - registry.address, - gasPriceMinimumFloor, - targetDensity, - adjustmentSpeed, - 0 - ) - }) - - describe('#initialize()', () => { - it('should have set the owner', async () => { - const owner: string = await gasPriceMinimum.owner() - assert.equal(owner, accounts[0]) - }) - - it('should set the gas price minimum', async () => { - const actualGasPriceMinimum = await gasPriceMinimum.getGasPriceMinimum(NULL_ADDRESS) - assertEqualBN(actualGasPriceMinimum, initialGasPriceMinimum) - }) - - it('should set the target density', async () => { - const actualTargetDensity = await gasPriceMinimum.targetDensity() - assertEqualBN(actualTargetDensity, targetDensity) - }) - - it('should set the adjustment speed', async () => { - const actualAdjustmentSpeed = await gasPriceMinimum.adjustmentSpeed() - assertEqualBN(actualAdjustmentSpeed, adjustmentSpeed) - }) - - it('should set the gas price minimum floor', async () => { - const actualGasPriceMinimumFloor = await gasPriceMinimum.gasPriceMinimumFloor() - assertEqualBN(actualGasPriceMinimumFloor, gasPriceMinimumFloor) - }) - - it('should not be callable again', async () => { - await assertTransactionRevertWithReason( - gasPriceMinimum.initialize( - registry.address, - gasPriceMinimumFloor, - targetDensity, - adjustmentSpeed, - 0 - ), - 'contract already initialized' - ) - }) - }) - - describe('#setAdjustmentSpeed', () => { - const newAdjustmentSpeed = toFixed(1 / 3) - - it('should set the adjustment speed', async () => { - await gasPriceMinimum.setAdjustmentSpeed(newAdjustmentSpeed) - const actualAdjustmentSpeed = await gasPriceMinimum.adjustmentSpeed() - assertEqualBN(actualAdjustmentSpeed, newAdjustmentSpeed) - }) - - it('should emit the AdjustmentSpeedSet event', async () => { - const resp = await gasPriceMinimum.setAdjustmentSpeed(newAdjustmentSpeed) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'AdjustmentSpeedSet', - args: { - adjustmentSpeed: newAdjustmentSpeed, - }, - }) - }) - - it('should revert when the provided fraction is greater than one', async () => { - await assertTransactionRevertWithReason( - gasPriceMinimum.setAdjustmentSpeed(toFixed(3 / 2)), - 'adjustment speed must be smaller than 1' - ) - }) - - it('should revert when called by anyone other than the owner', async () => { - await assertTransactionRevertWithReason( - gasPriceMinimum.setAdjustmentSpeed(newAdjustmentSpeed, { from: nonOwner }), - 'Ownable: caller is not the owner' - ) - }) - }) - - describe('#setTargetDensity', () => { - const newTargetDensity = toFixed(1 / 3) - - it('should set the adjustment speed', async () => { - await gasPriceMinimum.setTargetDensity(newTargetDensity) - const actualTargetDensity = await gasPriceMinimum.targetDensity() - assertEqualBN(actualTargetDensity, newTargetDensity) - }) - - it('should emit the TargetDensitySet event', async () => { - const resp = await gasPriceMinimum.setTargetDensity(newTargetDensity) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'TargetDensitySet', - args: { - targetDensity: newTargetDensity, - }, - }) - }) - - it('should revert when the provided fraction is greater than one', async () => { - await assertTransactionRevertWithReason( - gasPriceMinimum.setTargetDensity(toFixed(3 / 2)), - 'target density must be smaller than 1' - ) - }) - - it('should revert when called by anyone other than the owner', async () => { - await assertTransactionRevertWithReason( - gasPriceMinimum.setTargetDensity(newTargetDensity, { - from: nonOwner, - }), - 'Ownable: caller is not the owner' - ) - }) - }) - - describe('#setGasPriceMinimumFloor', () => { - const newGasPriceMinFloor = new BigNumber(150) - - it('should set the minimum gas price floor', async () => { - await gasPriceMinimum.setGasPriceMinimumFloor(newGasPriceMinFloor) - const actualFloor = await gasPriceMinimum.gasPriceMinimumFloor() - assertEqualBN(actualFloor, newGasPriceMinFloor) - }) - - it('should emit the MinimumGasPriceFloorSet event', async () => { - const resp = await gasPriceMinimum.setGasPriceMinimumFloor(newGasPriceMinFloor) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'GasPriceMinimumFloorSet', - args: { - gasPriceMinimumFloor: newGasPriceMinFloor, - }, - }) - }) - - it('should revert when the provided floor is zero', async () => { - await assertTransactionRevertWithReason( - gasPriceMinimum.setGasPriceMinimumFloor(0), - 'gas price minimum floor must be greater than zero' - ) - }) - - it('should revert when called by anyone other than the owner', async () => { - await assertTransactionRevertWithReason( - gasPriceMinimum.setGasPriceMinimumFloor(newGasPriceMinFloor, { - from: nonOwner, - }), - 'Ownable: caller is not the owner' - ) - }) - }) - - describe('#getUpdatedGasPriceMinimum', () => { - describe('when the block is full', () => { - it('should return 25% more than the initial minimum and should not be limited by the gas price minimum floor as a whole', async () => { - const currentGasPriceMinimum = await gasPriceMinimum.gasPriceMinimum() - await gasPriceMinimum.setGasPriceMinimumFloor(currentGasPriceMinimum) - const actualUpdatedGasPriceMinimum = await gasPriceMinimum.getUpdatedGasPriceMinimum(1, 1) - const expectedUpdatedGasPriceMinimum = currentGasPriceMinimum.times(5).div(4).plus(1) - assertEqualBN(actualUpdatedGasPriceMinimum, expectedUpdatedGasPriceMinimum) - }) - }) - - describe('when the block is empty', () => { - it('should return 25% less than the initial minimum, but be limited by the gas price minimum floor if new gas price lies below minimum', async () => { - const currentGasPriceMinimum = await gasPriceMinimum.gasPriceMinimum() - await gasPriceMinimum.setGasPriceMinimumFloor(currentGasPriceMinimum) - const actualUpdatedGasPriceMinimum = await gasPriceMinimum.getUpdatedGasPriceMinimum(0, 1) - const expectedCappedUpdatedGasPriceMinimum = await gasPriceMinimum.gasPriceMinimumFloor() - assertEqualBN(actualUpdatedGasPriceMinimum, expectedCappedUpdatedGasPriceMinimum) - }) - - it('should return 25% less than the initial minimum, but not be limited by the gas price minimum floor if new gas price lies above minimum', async () => { - const currentGasPriceMinimum = await gasPriceMinimum.gasPriceMinimum() - await gasPriceMinimum.setGasPriceMinimumFloor(1) - const actualUpdatedGasPriceMinimum = await gasPriceMinimum.getUpdatedGasPriceMinimum(0, 1) - const expectedUpdatedGasPriceMinimum = currentGasPriceMinimum.times(3).div(4).plus(1) - assertEqualBN(actualUpdatedGasPriceMinimum, expectedUpdatedGasPriceMinimum) - }) - }) - - describe('when the fullness of the block is random', () => { - const getUpdatedGasPriceMinimum = ( - gasPriceMinFloor, - previousGasPriceMinimum, - density, - _targetDensity, - _adjustmentSpeed - ) => { - const one = new BigNumber(1) - const newGasPriceMinimum = previousGasPriceMinimum - .times( - one.plus( - fromFixed(_adjustmentSpeed).times(fromFixed(density).minus(fromFixed(_targetDensity))) - ) - ) - .plus(one) - .integerValue(BigNumber.ROUND_DOWN) - - return newGasPriceMinimum.lt(gasPriceMinFloor) ? gasPriceMinFloor : newGasPriceMinimum - } - - it('should return an updated gas price minimum that matches a typescript implementation', async () => { - const numIterations = 100 - const currentGasPriceMinimum = await gasPriceMinimum.gasPriceMinimum() - const gasPriceMinFloor = currentGasPriceMinimum - await gasPriceMinimum.setGasPriceMinimumFloor(gasPriceMinFloor) - - for (let i = 0; i < numIterations; i++) { - const curGas = await gasPriceMinimum.gasPriceMinimum() - - const blockGasLimit = new BigNumber(web3.utils.randomHex(4)) - const gasUsed = BigNumber.random().times(blockGasLimit).integerValue() - const actualUpdatedGasPriceMinimum = await gasPriceMinimum.getUpdatedGasPriceMinimum( - gasUsed, - blockGasLimit - ) - - const expectedUpdatedGasPriceMinimum = getUpdatedGasPriceMinimum( - gasPriceMinFloor, - curGas, - toFixed(gasUsed.div(blockGasLimit)), - targetDensity, - adjustmentSpeed - ) - - assertEqualBN(actualUpdatedGasPriceMinimum, expectedUpdatedGasPriceMinimum) - } - }) - }) - }) -}) diff --git a/packages/protocol/test/common/integration.ts b/packages/protocol/test/common/integration.ts deleted file mode 100644 index 2f39b2912..000000000 --- a/packages/protocol/test/common/integration.ts +++ /dev/null @@ -1,751 +0,0 @@ -import { ensureLeading0x, NULL_ADDRESS } from '@celo/base/lib/address' -import { constitution } from '@celo/protocol/governanceConstitution' -import { - addressMinedLatestBlock, - assertEqualBN, - assertTransactionRevertWithReason, - assumeOwnershipWithTruffle, - stripHexEncoding, - timeTravel, -} from '@celo/protocol/lib/test-utils' -import { - getDeployedProxiedContract, - getFunctionSelectorsForContract, - makeTruffleContractForMigration, -} from '@celo/protocol/lib/web3-utils' -import { config } from '@celo/protocol/migrationsConfig' -import { linkedListChanges, zip } from '@celo/utils/lib/collections' -import { fixed1, toFixed } from '@celo/utils/lib/fixidity' -import BigNumber from 'bignumber.js' -import { - ElectionInstance, - FeeCurrencyWhitelistInstance, - FreezerInstance, - GoldTokenInstance, - GovernanceApproverMultiSigInstance, - GovernanceInstance, - GovernanceSlasherInstance, - LockedGoldInstance, - RegistryInstance, -} from 'types' -import { - ExchangeContract, - ExchangeInstance, - ReserveInstance, - ReserveSpenderMultiSigInstance, - SortedOraclesInstance, - StableTokenContract, - StableTokenInstance, -} from 'types/mento' -import { MENTO_PACKAGE } from '../../contractPackages' -import { ArtifactsSingleton } from '../../lib/artifactsSingleton' -import { SECONDS_IN_A_WEEK } from '../constants' - -enum VoteValue { - None = 0, - Abstain, - No, - Yes, -} - -async function getGroups(election: ElectionInstance) { - const [lst1, lst2] = await election.getTotalVotesForEligibleValidatorGroups() - return zip( - (address, value) => { - return { address, value } - }, - lst1, - lst2 - ) -} - -// Returns how much voting gold will be decremented from the groups voted by an account -async function slashingOfGroups( - account: string, - penalty: BigNumber, - lockedGold: LockedGoldInstance, - election: ElectionInstance -) { - // first check how much voting gold has to be slashed - const nonVoting = await lockedGold.getAccountNonvotingLockedGold(account) - if (penalty.isLessThan(nonVoting)) { - return [] - } - let difference = penalty.minus(nonVoting) - // find voted groups - const groups = await election.getGroupsVotedForByAccount(account) - const res = [] - // - for (let i = groups.length - 1; i >= 0; i--) { - const group = groups[i] - const totalVotes = await election.getTotalVotesForGroup(group) - const votes = await election.getTotalVotesForGroupByAccount(group, account) - const slashedVotes = votes.lt(difference) ? votes : difference - res.push({ address: group, value: totalVotes.minus(slashedVotes), index: i }) - difference = difference.minus(slashedVotes) - if (difference.eq(new BigNumber(0))) { - break - } - } - return res -} - -async function findLessersAndGreaters( - account: string, - penalty: BigNumber, - lockedGold: LockedGoldInstance, - election: ElectionInstance -) { - const groups = await getGroups(election) - const changed = await slashingOfGroups(account, penalty, lockedGold, election) - const changes = linkedListChanges(groups, changed) - return { ...changes, indices: changed.map((a) => a.index) } -} - -contract('Integration: Running elections', (_accounts: string[]) => { - let election: ElectionInstance - - before(async () => { - election = await getDeployedProxiedContract('Election', artifacts) - }) - - describe('When getting the elected validators', () => { - it('should elect all 30 validators', async () => { - const elected = await election.electValidatorSigners() - assert.equal(elected.length, 30) - }) - it('should elect specified number validators with electNValidatorSigners', async () => { - const elected = await election.electNValidatorSigners(1, 20) - assert.equal(elected.length, 20) - }) - }) -}) - -contract('Integration: Governance slashing', (accounts: string[]) => { - const proposalId = 1 - const dequeuedIndex = 0 - let lockedGold: LockedGoldInstance - let election: ElectionInstance - let multiSig: GovernanceApproverMultiSigInstance - let governance: GovernanceInstance - let governanceSlasher: GovernanceSlasherInstance - let proposalTransactions: any - let value: BigNumber - let valueOfSlashed: BigNumber - const penalty = new BigNumber('100') - const slashedAccount = accounts[9] - - before(async () => { - lockedGold = await getDeployedProxiedContract('LockedGold', artifacts) - election = await getDeployedProxiedContract('Election', artifacts) - // @ts-ignore - await lockedGold.lock({ value: '10000000000000000000000000' }) - - multiSig = await getDeployedProxiedContract('GovernanceApproverMultiSig', artifacts) - governance = await getDeployedProxiedContract('Governance', artifacts) - governanceSlasher = await getDeployedProxiedContract('GovernanceSlasher', artifacts) - value = await lockedGold.getAccountTotalLockedGold(accounts[0]) - - proposalTransactions = [ - { - value: 0, - destination: governanceSlasher.address, - data: Buffer.from( - stripHexEncoding( - // @ts-ignore - governanceSlasher.contract.methods.approveSlashing(slashedAccount, 100).encodeABI() - ), - 'hex' - ), - }, - ] - }) - - describe('When making a governance proposal', () => { - before(async () => { - await governance.propose( - proposalTransactions.map((x: any) => x.value), - proposalTransactions.map((x: any) => x.destination), - // @ts-ignore - Buffer.concat(proposalTransactions.map((x: any) => x.data)), - proposalTransactions.map((x: any) => x.data.length), - 'URL', - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: web3.utils.toWei(config.governance.minDeposit.toString(), 'ether') } - ) - }) - - it('should increment the proposal count', async () => { - assert.equal((await governance.proposalCount()).toNumber(), proposalId) - }) - }) - - describe('When upvoting that proposal', () => { - before(async () => { - await governance.upvote(proposalId, 0, 0) - }) - - it('should increase the number of upvotes for the proposal', async () => { - assertEqualBN(await governance.getUpvotes(proposalId), value) - }) - }) - - describe('When approving that proposal', () => { - before(async () => { - await timeTravel(config.governance.dequeueFrequency, web3) - // @ts-ignore - const txData = governance.contract.methods.approve(proposalId, dequeuedIndex).encodeABI() - await multiSig.submitTransaction(governance.address, 0, txData, { - from: accounts[0], - }) - }) - - it('should set the proposal to approved', async () => { - assert.isTrue(await governance.isApproved(proposalId)) - }) - }) - - describe('When voting on that proposal', () => { - before(async () => { - await timeTravel(config.governance.approvalStageDuration, web3) - await governance.vote(proposalId, dequeuedIndex, VoteValue.Yes) - }) - - it('should increment the vote totals', async () => { - const [yes, ,] = await governance.getVoteTotals(proposalId) - assertEqualBN(yes, value) - }) - }) - - describe('When executing that proposal', () => { - before(async () => { - await timeTravel(config.governance.referendumStageDuration, web3) - await governance.execute(proposalId, dequeuedIndex) - }) - - it('should execute the proposal', async () => { - assertEqualBN(await governanceSlasher.getApprovedSlashing(slashedAccount), penalty) - }) - }) - - describe('When performing slashing', () => { - before(async () => { - await timeTravel(config.governance.referendumStageDuration, web3) - valueOfSlashed = await lockedGold.getAccountTotalLockedGold(slashedAccount) - const { lessers, greaters, indices } = await findLessersAndGreaters( - slashedAccount, - penalty, - lockedGold, - election - ) - await governanceSlasher.slash(slashedAccount, lessers, greaters, indices) - }) - - it('should set approved slashing to zero', async () => { - assert.equal((await governanceSlasher.getApprovedSlashing(slashedAccount)).toNumber(), 0) - }) - - it('should slash the account', async () => { - assertEqualBN( - await lockedGold.getAccountTotalLockedGold(slashedAccount), - valueOfSlashed.minus(penalty) - ) - }) - }) -}) - -contract('Integration: Governance', (accounts: string[]) => { - const proposalId = 1 - const dequeuedIndex = 0 - let lockedGold: LockedGoldInstance - let multiSig: GovernanceApproverMultiSigInstance - let governance: GovernanceInstance - let registry: RegistryInstance - let proposalTransactions: any - let value: BigNumber - - before(async () => { - lockedGold = await getDeployedProxiedContract('LockedGold', artifacts) - // @ts-ignore - await lockedGold.lock({ value: '10000000000000000000000000' }) - value = await lockedGold.getAccountTotalLockedGold(accounts[0]) - multiSig = await getDeployedProxiedContract('GovernanceApproverMultiSig', artifacts) - governance = await getDeployedProxiedContract('Governance', artifacts) - registry = await getDeployedProxiedContract('Registry', artifacts) - proposalTransactions = [ - { - value: 0, - destination: registry.address, - data: Buffer.from( - stripHexEncoding( - // @ts-ignore - registry.contract.methods.setAddressFor('test1', accounts[1]).encodeABI() - ), - 'hex' - ), - }, - { - value: 0, - destination: registry.address, - data: Buffer.from( - stripHexEncoding( - // @ts-ignore - registry.contract.methods.setAddressFor('test2', accounts[2]).encodeABI() - ), - 'hex' - ), - }, - ] - }) - - describe('Checking governance thresholds', () => { - for (const contractName of Object.keys(constitution).filter((k) => k !== 'proxy')) { - it('should have correct thresholds for ' + contractName, async () => { - const artifactsInstance = ArtifactsSingleton.getInstance( - constitution[contractName].__contractPackage, - artifacts - ) - - const contract = await getDeployedProxiedContract( - contractName, - artifactsInstance - ) - - const selectors = getFunctionSelectorsForContract(contract, contractName, artifactsInstance) - - selectors.default = ['0x00000000'] - - const thresholds = { ...constitution.proxy, ...constitution[contractName] } - await Promise.all( - Object.keys(thresholds) - .filter((k) => k !== '__contractPackage') - .map((func) => - Promise.all( - selectors[func].map(async (selector) => { - assertEqualBN( - await governance.getConstitution(contract.address, selector), - toFixed(thresholds[func]), - 'Threshold set incorrectly for function ' + func - ) - }) - ) - ) - ) - }) - } - }) - - describe('When making a governance proposal', () => { - before(async () => { - await governance.propose( - proposalTransactions.map((x: any) => x.value), - proposalTransactions.map((x: any) => x.destination), - // @ts-ignore - Buffer.concat(proposalTransactions.map((x: any) => x.data)), - proposalTransactions.map((x: any) => x.data.length), - 'URL', - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: web3.utils.toWei(config.governance.minDeposit.toString(), 'ether') } - ) - }) - - it('should increment the proposal count', async () => { - assert.equal((await governance.proposalCount()).toNumber(), proposalId) - }) - }) - - describe('When upvoting that proposal', () => { - before(async () => { - await governance.upvote(proposalId, 0, 0) - }) - - it('should increase the number of upvotes for the proposal', async () => { - assertEqualBN(await governance.getUpvotes(proposalId), value) - }) - }) - - describe('When approving that proposal', () => { - before(async () => { - await timeTravel(config.governance.dequeueFrequency, web3) - // @ts-ignore - const txData = governance.contract.methods.approve(proposalId, dequeuedIndex).encodeABI() - await multiSig.submitTransaction(governance.address, 0, txData, { - from: accounts[0], - }) - }) - - it('should set the proposal to approved', async () => { - assert.isTrue(await governance.isApproved(proposalId)) - }) - }) - - describe('When voting on that proposal', () => { - before(async () => { - await timeTravel(config.governance.approvalStageDuration, web3) - await governance.vote(proposalId, dequeuedIndex, VoteValue.Yes) - }) - - it('should increment the vote totals', async () => { - const [yes, ,] = await governance.getVoteTotals(proposalId) - assertEqualBN(yes, value) - }) - }) - - describe('When executing that proposal', () => { - before(async () => { - await timeTravel(config.governance.referendumStageDuration, web3) - await governance.execute(proposalId, dequeuedIndex) - }) - - it('should execute the proposal', async () => { - assert.equal(await registry.getAddressForOrDie(web3.utils.soliditySha3('test1')), accounts[1]) - assert.equal(await registry.getAddressForOrDie(web3.utils.soliditySha3('test2')), accounts[2]) - }) - }) -}) - -Array.from([ - ['Exchange', 'StableToken'], // USD - ['ExchangeEUR', 'StableTokenEUR'], // EUR - ['ExchangeBRL', 'StableTokenBRL'], // BRL (cREAL) -]).forEach(([exchangeId, stableTokenId]) => - contract(`Integration: ${exchangeId} ${stableTokenId}`, (accounts: string[]) => { - const transferAmount = 10 - let exchange: ExchangeInstance - let multiSig: ReserveSpenderMultiSigInstance - let reserve: ReserveInstance - let goldToken: GoldTokenInstance - let stableToken: StableTokenInstance - let originalStable - let originalGold - let originalReserve - let finalStable: BigNumber - let finalGold: BigNumber - let finalReserve: BigNumber - - const decimals = 18 - - before(async () => { - exchange = await getDeployedProxiedContract( - exchangeId, - ArtifactsSingleton.getInstance(MENTO_PACKAGE) - ) - stableToken = await getDeployedProxiedContract( - stableTokenId, - ArtifactsSingleton.getInstance(MENTO_PACKAGE) - ) - multiSig = await getDeployedProxiedContract( - 'ReserveSpenderMultiSig', - ArtifactsSingleton.getInstance(MENTO_PACKAGE) - ) - reserve = await getDeployedProxiedContract( - 'Reserve', - ArtifactsSingleton.getInstance(MENTO_PACKAGE) - ) - goldToken = await getDeployedProxiedContract('GoldToken', artifacts) - }) - - describe('Selling', () => { - const sellAmount = new BigNumber('1000000000000000000000') - const minBuyAmount = 1 - - describe('When selling gold', () => { - before(async () => { - originalStable = await stableToken.balanceOf(accounts[0]) - originalGold = await goldToken.balanceOf(accounts[0]) - originalReserve = await goldToken.balanceOf(reserve.address) - await goldToken.approve(exchange.address, sellAmount) - await exchange.sell(sellAmount, minBuyAmount, true) - finalStable = await stableToken.balanceOf(accounts[0]) - finalGold = await goldToken.balanceOf(accounts[0]) - finalReserve = await goldToken.balanceOf(reserve.address) - }) - - it(`should increase user's stable`, async () => { - assert.isTrue(finalStable.gt(originalStable)) - }) - - it(`should reduce user's gold`, async () => { - if (await addressMinedLatestBlock(accounts[0])) { - const blockReward = new BigNumber(2).times(new BigNumber(10).pow(decimals)) - assert.isTrue(finalGold.lt(originalGold.plus(blockReward))) - } else { - assert.isTrue(finalGold.lt(originalGold)) - } - }) - - it(`should increase Reserve's gold`, async () => { - assert.isTrue(finalReserve.gt(originalReserve)) - }) - }) - - // Note that this test relies on having purchased stable token in the previous test. - describe('When selling stable token', () => { - before(async () => { - originalStable = await stableToken.balanceOf(accounts[0]) - originalGold = await goldToken.balanceOf(accounts[0]) - originalReserve = await goldToken.balanceOf(reserve.address) - await stableToken.approve(exchange.address, sellAmount) - // Cannot sell more than was purchased in the previous test. - await exchange.sell(sellAmount.div(20), minBuyAmount, false) - finalStable = await stableToken.balanceOf(accounts[0]) - finalGold = await goldToken.balanceOf(accounts[0]) - finalReserve = await goldToken.balanceOf(reserve.address) - }) - - it(`should reduce user's stable`, async () => { - assert.isTrue(finalStable.lt(originalStable)) - }) - - it(`should increase user's gold`, async () => { - assert.isTrue(finalGold.gt(originalGold)) - }) - - it(`should reduce Reserve's gold`, async () => { - assert.isTrue(finalReserve.lt(originalReserve)) - }) - }) - }) - - describe('Buying', () => { - const buyAmount = new BigNumber(10000000000000000000) - const maxSellAmount = new BigNumber('10000000000000000000000') - - describe('When buying stable token', () => { - before(async () => { - originalStable = await stableToken.balanceOf(accounts[0]) - originalGold = await goldToken.balanceOf(accounts[0]) - originalReserve = await goldToken.balanceOf(reserve.address) - await goldToken.approve(exchange.address, maxSellAmount) - await exchange.buy(buyAmount, maxSellAmount, false) - finalStable = await stableToken.balanceOf(accounts[0]) - finalGold = await goldToken.balanceOf(accounts[0]) - finalReserve = await goldToken.balanceOf(reserve.address) - }) - - it(`should increase user's stable`, async () => { - assert.isTrue(finalStable.gt(originalStable)) - }) - - it(`should reduce user's gold`, async () => { - if (await addressMinedLatestBlock(accounts[0])) { - const blockReward = new BigNumber(2).times(new BigNumber(10).pow(decimals)) - assert.isTrue(finalGold.lt(originalGold.plus(blockReward))) - } else { - assert.isTrue(finalGold.lt(originalGold)) - } - }) - - it(`should increase Reserve's gold`, async () => { - assert.isTrue(finalReserve.gt(originalReserve)) - }) - }) - - // Note that this test relies on having purchased cUSD in a previous test - describe('When buying celo', () => { - before(async () => { - originalStable = await stableToken.balanceOf(accounts[0]) - originalGold = await goldToken.balanceOf(accounts[0]) - originalReserve = await goldToken.balanceOf(reserve.address) - await stableToken.approve(exchange.address, maxSellAmount) - // Cannot sell more than was purchased in the previous test. - await exchange.buy(buyAmount, maxSellAmount, true) - finalStable = await stableToken.balanceOf(accounts[0]) - finalGold = await goldToken.balanceOf(accounts[0]) - finalReserve = await goldToken.balanceOf(reserve.address) - }) - - it(`should reduce user's stable`, async () => { - assert.isTrue(finalStable.lt(originalStable)) - }) - - it(`should increase user's gold`, async () => { - assert.isTrue(finalGold.gt(originalGold)) - }) - - it(`should reduce Reserve's gold`, async () => { - assert.isTrue(finalReserve.lt(originalReserve)) - }) - }) - }) - - describe('When transferring gold', () => { - const otherReserveAddress = '0x7457d5E02197480Db681D3fdF256c7acA21bDc12' - let originalOtherAccount - beforeEach(async () => { - originalReserve = await goldToken.balanceOf(reserve.address) - originalOtherAccount = await goldToken.balanceOf(otherReserveAddress) - }) - - it(`should transfer gold`, async () => { - // @ts-ignore - const txData = reserve.contract.methods - .transferGold(otherReserveAddress, transferAmount) - .encodeABI() - await multiSig.submitTransaction(reserve.address, 0, txData, { - from: accounts[0], - }) - assert.isTrue( - (await goldToken.balanceOf(reserve.address)).isEqualTo( - originalReserve.minus(transferAmount) - ) - ) - assert.isTrue( - (await goldToken.balanceOf(otherReserveAddress)).isEqualTo( - originalOtherAccount.plus(transferAmount) - ) - ) - }) - }) - }) -) - -contract('Integration: Adding StableToken', (accounts: string[]) => { - const Exchange: ExchangeContract = makeTruffleContractForMigration( - 'Exchange', - MENTO_PACKAGE, - web3 - ) - const StableToken: StableTokenContract = makeTruffleContractForMigration( - 'StableToken', - MENTO_PACKAGE, - web3 - ) - let exchangeAbc: ExchangeInstance - let freezer: FreezerInstance - let goldToken: GoldTokenInstance - let stableTokenAbc: StableTokenInstance - const sellAmount = web3.utils.toWei('0.1', 'ether') - const minBuyAmount = 1 - - // 0. Make ourselves the owner of the various contracts we will need to interact with, as - // passing a governance proposal for each one will be a pain in the butt. - before(async () => { - goldToken = await getDeployedProxiedContract('GoldToken', artifacts) - freezer = await getDeployedProxiedContract('Freezer', artifacts) - const contractsToOwn = ['Freezer', 'Registry', 'SortedOracles', 'FeeCurrencyWhitelist'] - await assumeOwnershipWithTruffle(contractsToOwn, accounts[0]) - await assumeOwnershipWithTruffle(['Reserve'], accounts[0], 0, MENTO_PACKAGE) - }) - - // 1. Mimic the state of the world post-contracts-release - // a) Deploy the contracts. For simplicity, omit proxies for now. - // b) Register the contracts - // c) Initialize the contracts - // d) Confirm mento is effectively frozen - describe('When the contracts have been deployed and initialized', () => { - before(async () => { - exchangeAbc = await Exchange.new(true) - stableTokenAbc = await StableToken.new(true) - - const registry: RegistryInstance = await getDeployedProxiedContract('Registry', artifacts) - await registry.setAddressFor('ExchangeABC', exchangeAbc.address) - await registry.setAddressFor('StableTokenABC', stableTokenAbc.address) - - await stableTokenAbc.initialize( - 'Celo Abc', // Name - 'cABC', // symbol - '18', // decimals - registry.address, - fixed1, // inflationRate - SECONDS_IN_A_WEEK, // inflationRatePeriod - [accounts[0]], // pre-mint account - ['1000000000000000000'], // pre-mint amount - 'ExchangeABC' // exchange contract key on the registry - ) - await exchangeAbc.initialize( - registry.address, - 'StableTokenABC', - '5000000000000000000000', // spread, matches mainnet for cUSD and cEUR - '1300000000000000000000', // reserveFraction, matches mainnet for cEUR - '300', // updateFrequency, matches mainnet for cUSD and cEUR - '1' // minimumReports, minimum possible to avoid having to mock multiple reports - ) - }) - - it(`should be impossible to sell CELO`, async () => { - await goldToken.approve(exchangeAbc.address, sellAmount) - await assertTransactionRevertWithReason( - exchangeAbc.sell(sellAmount, minBuyAmount, true), - 'token address cannot be null' - ) - }) - - it(`should be impossible to sell stable token`, async () => { - await stableTokenAbc.approve(exchangeAbc.address, sellAmount) - await assertTransactionRevertWithReason( - exchangeAbc.sell(sellAmount, minBuyAmount, false), - 'token address cannot be null' - ) - }) - }) - - // 2. Mimic the state of the world post-oracle-activation-proposal - // a) Activate the oracles and freeze the mento - // b) Make an oracle report - // c) Confirm mento is effectively frozen - describe('When the contracts have been frozen and an oracle report has been made', () => { - before(async () => { - const sortedOracles: SortedOraclesInstance = await getDeployedProxiedContract( - 'SortedOracles', - artifacts - ) - await sortedOracles.addOracle(stableTokenAbc.address, ensureLeading0x(accounts[0])) - await freezer.freeze(stableTokenAbc.address) - await freezer.freeze(exchangeAbc.address) - await sortedOracles.report(stableTokenAbc.address, toFixed(1), NULL_ADDRESS, NULL_ADDRESS) - }) - - it(`should be impossible to sell CELO`, async () => { - await goldToken.approve(exchangeAbc.address, sellAmount) - await assertTransactionRevertWithReason( - exchangeAbc.sell(sellAmount, minBuyAmount, true), - "can't call when contract is frozen" - ) - }) - - it(`should be impossible to sell stable token`, async () => { - await stableTokenAbc.approve(exchangeAbc.address, sellAmount) - await assertTransactionRevertWithReason( - exchangeAbc.sell(sellAmount, minBuyAmount, false), - "can't call when contract is frozen" - ) - }) - }) - - // 3. Mimic the state of the world post-mento-activation-proposal - // a) Add the stable token to the reserve - // b) Unfreeze the mento - // c) Confirm mento is functional - describe('When the contracts have been unfrozen and the mento has been activated', () => { - before(async () => { - const reserve: ReserveInstance = await getDeployedProxiedContract( - 'Reserve', - ArtifactsSingleton.getInstance(MENTO_PACKAGE) - ) - const feeCurrencyWhitelist: FeeCurrencyWhitelistInstance = await getDeployedProxiedContract( - 'FeeCurrencyWhitelist', - artifacts - ) - await reserve.addToken(stableTokenAbc.address) - await reserve.addExchangeSpender(exchangeAbc.address) - await freezer.unfreeze(stableTokenAbc.address) - await freezer.unfreeze(exchangeAbc.address) - - // activate stable during mento-activation proposal - await exchangeAbc.activateStable() - // Fee currency can't be tested here, but keep this line for reference - await feeCurrencyWhitelist.addToken(stableTokenAbc.address) - }) - - it(`should be possible to sell CELO`, async () => { - await goldToken.approve(exchangeAbc.address, sellAmount) - await exchangeAbc.sell(sellAmount, minBuyAmount, true) - }) - - it(`should be possible to sell stable token`, async () => { - await stableTokenAbc.approve(exchangeAbc.address, sellAmount) - await exchangeAbc.sell(sellAmount, minBuyAmount, false) - }) - }) -}) diff --git a/packages/protocol/test/common/metatransactionwallet.ts b/packages/protocol/test/common/metatransactionwallet.ts deleted file mode 100644 index 7a073ca70..000000000 --- a/packages/protocol/test/common/metatransactionwallet.ts +++ /dev/null @@ -1,607 +0,0 @@ -import { - constructMetaTransactionExecutionDigest, - getDomainDigest, - getSignatureForMetaTransaction, -} from '@celo/protocol/lib/meta-tx-utils' -import { - assertEqualBN, - assertLogMatches2, - // tslint:disable-next-line: ordered-imports - assertTransactionRevertWithReason, - assertTransactionRevertWithoutReason, -} from '@celo/protocol/lib/test-utils' -import { ensureLeading0x, trimLeading0x } from '@celo/utils/lib/address' -import { MetaTransactionWalletContract, MetaTransactionWalletInstance } from 'types' - -const MetaTransactionWallet: MetaTransactionWalletContract = - artifacts.require('MetaTransactionWallet') - -contract('MetaTransactionWallet', (accounts: string[]) => { - let wallet: MetaTransactionWalletInstance - let initializeRes - const signer = accounts[1] - const nonSigner = accounts[2] - - const executeOnSelf = (data: string, value = 0) => - // @ts-ignore - wallet.executeTransaction(wallet.address, value, data, { from: signer }) - - beforeEach(async () => { - wallet = await MetaTransactionWallet.new(true) - initializeRes = await wallet.initialize(signer) - }) - - describe('#EIP712_EXECUTE_META_TRANSACTION_TYPEHASH()', () => { - it('should have set the right typehash', async () => { - const expectedTypehash = web3.utils.soliditySha3( - 'ExecuteMetaTransaction(address destination,uint256 value,bytes data,uint256 nonce)' - ) - assert.equal(await wallet.EIP712_EXECUTE_META_TRANSACTION_TYPEHASH(), expectedTypehash) - }) - }) - - describe('#initialize()', () => { - it('should have set the owner to itself', async () => { - assert.equal(await wallet.owner(), wallet.address) - }) - - it('should have set the signer', async () => { - assert.equal(await wallet.signer(), signer) - }) - - it('should have set the EIP-712 domain separator', async () => { - assert.equal(await wallet.eip712DomainSeparator(), getDomainDigest(wallet.address)) - }) - - it('should emit the SignerSet event', () => { - assertLogMatches2(initializeRes.logs[0], { - event: 'SignerSet', - args: { - signer, - }, - }) - }) - - it('should emit the EIP712DomainSeparatorSet event', () => { - assertLogMatches2(initializeRes.logs[1], { - event: 'EIP712DomainSeparatorSet', - args: { - eip712DomainSeparator: getDomainDigest(wallet.address), - }, - }) - }) - - it('should emit the OwnershipTransferred event', () => { - assertLogMatches2(initializeRes.logs[2], { - event: 'OwnershipTransferred', - args: { - previousOwner: accounts[0], - newOwner: wallet.address, - }, - }) - }) - - it('should not be callable again', async () => { - await assertTransactionRevertWithReason( - wallet.initialize(signer), - 'contract already initialized' - ) - }) - }) - - describe('fallback function', () => { - describe('when receiving celo', () => { - it('emits Deposit event with correct parameters', async () => { - const value = 100 - // @ts-ignore - const res = await wallet.send(value) - assertLogMatches2(res.logs[0], { - event: 'Deposit', - args: { - sender: accounts[0], - value, - }, - }) - }) - }) - - describe('when receiving 0 value', () => { - it('does not emit an event', async () => { - // @ts-ignore - const res = await wallet.send(0) - assert.equal(res.logs, 0) - }) - }) - }) - - describe('#setSigner()', () => { - const newSigner = accounts[3] - - describe('when called by the wallet contract', () => { - let res - beforeEach(async () => { - // @ts-ignore - const data = wallet.contract.methods.setSigner(newSigner).encodeABI() - res = await executeOnSelf(data) - }) - it('should set a new signer', async () => { - assert.equal(await wallet.signer(), newSigner) - }) - it('should emit the SignerSet event', async () => { - assertLogMatches2(res.logs[0], { - event: 'SignerSet', - args: { - signer: newSigner, - }, - }) - }) - }) - - describe('when called by the signer', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - wallet.setSigner(newSigner, { from: signer }), - 'Ownable: caller is not the owner' - ) - }) - }) - }) - - describe('#setGuardian()', () => { - const guardian = accounts[4] - - describe('when called by the wallet contract', () => { - let res - beforeEach(async () => { - // @ts-ignore - const data = wallet.contract.methods.setGuardian(guardian).encodeABI() - res = await executeOnSelf(data) - }) - it('should set a new guardian', async () => { - assert.equal(await wallet.guardian(), guardian) - }) - it('should emit the GuardianSet event', async () => { - assertLogMatches2(res.logs[0], { - event: 'GuardianSet', - args: { - guardian, - }, - }) - }) - }) - - describe('when not called by the wallet contract', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - wallet.setGuardian(guardian, { from: nonSigner }), - 'Ownable: caller is not the owner' - ) - }) - }) - }) - - describe('#recoverWallet()', () => { - const newSigner = accounts[3] - const guardian = accounts[4] - const nonGuardian = accounts[5] - - describe('When the guardian is set', async () => { - let res - beforeEach(async () => { - // @ts-ignore - const data = wallet.contract.methods.setGuardian(guardian).encodeABI() - await executeOnSelf(data) - }) - - it('guardian should be able to recover wallet and update signer', async () => { - assert.notEqual(await wallet.signer(), newSigner) - res = await wallet.recoverWallet(newSigner, { from: guardian }) - assert.equal(await wallet.signer(), newSigner) - }) - - it('should emit the SignerSet event', async () => { - assertLogMatches2(res.logs[1], { - event: 'WalletRecovered', - args: { - newSigner, - }, - }) - }) - - it('non guardian should not be able to recover wallet', async () => { - await assertTransactionRevertWithReason( - wallet.recoverWallet(newSigner, { from: nonGuardian }), - 'Caller is not the guardian' - ) - }) - }) - - describe('when the guardian is not set', () => { - it('should not be able to recover wallet', async () => { - await assertTransactionRevertWithReason( - wallet.recoverWallet(newSigner, { from: guardian }), - 'Caller is not the guardian' - ) - }) - }) - }) - - describe('#executeTransaction()', () => { - describe('when the destination is a contract', () => { - let res: any - let data: string - let destination: string - const value = 0 - beforeEach(async () => { - destination = wallet.address - // @ts-ignore - data = wallet.contract.methods.setSigner(nonSigner).encodeABI() - }) - - describe('when the caller is the signer', () => { - beforeEach(async () => { - res = await wallet.executeTransaction(destination, value, data, { from: signer }) - }) - - it('should execute the transaction', async () => { - assert.equal(await wallet.signer(), nonSigner) - }) - - it('should not increment the nonce', async () => { - assertEqualBN(await wallet.nonce(), 0) - }) - - it('should emit the TransactionExecution event', () => { - assertLogMatches2(res.logs[1], { - event: 'TransactionExecution', - args: { - destination, - value, - data, - returnData: null, - }, - }) - }) - }) - - describe('when the caller is not the signer', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - wallet.executeTransaction(destination, value, data, { from: nonSigner }), - 'Invalid transaction sender' - ) - }) - }) - }) - - describe('when the destination is not a contract', () => { - const value = 100 - const destination = web3.utils.toChecksumAddress(web3.utils.randomHex(20)) - describe('when the caller is the signer', () => { - describe('when data is empty', () => { - let res: any - const data = '0x' - beforeEach(async () => { - await web3.eth.sendTransaction({ from: accounts[0], to: wallet.address, value }) - // @ts-ignore - res = await wallet.executeTransaction(destination, value, data, { from: signer }) - }) - - it('should execute the transaction', async () => { - assert.equal(await web3.eth.getBalance(destination), value) - }) - - it('should not increment the nonce', async () => { - assertEqualBN(await wallet.nonce(), 0) - }) - - it('should emit the TransactionExecution event', () => { - assertLogMatches2(res.logs[0], { - event: 'TransactionExecution', - args: { - destination, - value, - data: null, - returnData: null, - }, - }) - }) - }) - - describe('when data is not empty', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - wallet.executeTransaction(destination, value, '0x1234', { from: signer }), - 'Invalid contract address' - ) - }) - }) - }) - }) - }) - - describe('#executeTransactions()', () => { - describe('when the transactions are a mix of contract and non-contract calls', () => { - const value = 100 - let transactions: any[] - beforeEach(async () => { - transactions = [ - // CELO transfer - { - destination: web3.utils.toChecksumAddress(web3.utils.randomHex(20)), - value, - data: '0x', - }, - - // No-op transfer ownership - { - destination: wallet.address, - value: 0, - // @ts-ignore - data: wallet.contract.methods.transferOwnership(wallet.address).encodeABI(), - }, - - // CELO transfer - { - destination: web3.utils.toChecksumAddress(web3.utils.randomHex(20)), - value, - data: '0x', - }, - - // view signer (to test return values) - { - destination: wallet.address, - value: 0, - // @ts-ignore - data: wallet.contract.methods.signer().encodeABI(), - }, - - // view isOwner (to test return values) - { - destination: wallet.address, - value: 0, - // @ts-ignore - data: wallet.contract.methods.isOwner().encodeABI(), - }, - - // Change signer - { - destination: wallet.address, - value: 0, - // @ts-ignore - data: wallet.contract.methods.setSigner(nonSigner).encodeABI(), - }, - ] - - await web3.eth.sendTransaction({ - from: accounts[0], - to: wallet.address, - value: value * 2, - }) - }) - - describe('when the caller is the signer', () => { - describe('when the transactions are executed directly', () => { - describe('', () => { - beforeEach(async () => { - await wallet.executeTransactions( - transactions.map((t) => t.destination), - transactions.map((t) => t.value), - ensureLeading0x(transactions.map((t) => trimLeading0x(t.data)).join('')), - transactions.map((t) => trimLeading0x(t.data).length / 2), - { from: signer } - ) - }) - - it('should execute the transactions', async () => { - assert.equal(await web3.eth.getBalance(transactions[0].destination), value) - assert.equal(await web3.eth.getBalance(transactions[2].destination), value) - assert.equal(await wallet.signer(), nonSigner) - }) - - it('should not increment the nonce', async () => { - assertEqualBN(await wallet.nonce(), 0) - }) - }) - - it('returns the proper values', async () => { - const boolTrueReturned: string = '01' - const signerAddrReturned: string = trimLeading0x(signer).toLowerCase() - const viewSignerTxIndex: number = 3 - const isOwnerTxIndex: number = 4 - - const returnValues = await wallet.executeTransactions.call( - transactions.map((t) => t.destination), - transactions.map((t) => t.value), - ensureLeading0x(transactions.map((t) => trimLeading0x(t.data)).join('')), - transactions.map((t) => trimLeading0x(t.data).length / 2), - { from: signer } - ) - - assert.equal( - returnValues[0], - // return values are padded to have a length of 32 bytes - `0x${signerAddrReturned.padStart(64, '0')}${boolTrueReturned.padStart(64, '0')}` - ) - for (const i of returnValues[1].keys()) { - if (i === viewSignerTxIndex || i === isOwnerTxIndex) { - assert.equal(web3.utils.hexToNumber(returnValues[1][i]), 32) - } else { - assert.equal(web3.utils.hexToNumber(returnValues[1][i]), 0) - } - } - }) - }) - - describe('when the data parameter has extra bytes appended', () => { - it('reverts', async () => { - await assertTransactionRevertWithReason( - wallet.executeTransactions( - transactions.map((t) => t.destination), - transactions.map((t) => t.value), - ensureLeading0x(transactions.map((t) => trimLeading0x(t.data)).join('deadbeef')), - transactions.map((t) => trimLeading0x(t.data).length / 2), - { from: signer } - ), - 'data cannot have extra bytes appended' - ) - }) - }) - - describe('when dataLengths has erroneous lengths', () => { - it('reverts', async () => { - await assertTransactionRevertWithoutReason( - wallet.executeTransactions( - transactions.map((t) => t.destination), - transactions.map((t) => t.value), - ensureLeading0x(transactions.map((t) => trimLeading0x(t.data)).join('deadbeef')), - transactions.map((t) => trimLeading0x(t.data).length), // invalid lengths without /2 - { from: signer } - ) - ) - }) - }) - - describe('when the transactions are executed as a meta-transaction', () => { - beforeEach(async () => { - // @ts-ignore - const data = wallet.contract.methods - .executeTransactions( - transactions.map((t) => t.destination), - transactions.map((t) => t.value), - ensureLeading0x(transactions.map((t) => trimLeading0x(t.data)).join('')), - transactions.map((t) => trimLeading0x(t.data).length / 2) - ) - .encodeABI() - const { v, r, s } = await getSignatureForMetaTransaction(signer, wallet.address, { - destination: wallet.address, - value: 0, - data, - nonce: 0, - }) - await wallet.executeMetaTransaction(wallet.address, 0, data, v, r, s, { - from: signer, - }) - }) - - it('should execute the transactions', async () => { - assert.equal(await web3.eth.getBalance(transactions[0].destination), value) - assert.equal(await web3.eth.getBalance(transactions[2].destination), value) - assert.equal(await wallet.signer(), nonSigner) - }) - - it('should increment the nonce', async () => { - assertEqualBN(await wallet.nonce(), 1) - }) - }) - }) - }) - }) - - describe('#getMetaTransactionDigest', () => { - it('creates the digest as expected', async () => { - const value = 100 - const destination = web3.utils.toChecksumAddress(web3.utils.randomHex(20)) - const data = '0x' - const nonce = 0 - - const digest = constructMetaTransactionExecutionDigest(wallet.address, { - value, - destination, - data, - nonce, - }) - - assert.equal(await wallet.getMetaTransactionDigest(destination, value, data, nonce), digest) - }) - }) - - describe('#executeMetaTransaction()', () => { - const value = 100 - const destination = web3.utils.toChecksumAddress(web3.utils.randomHex(20)) - const data = '0x' - let submitter - let nonce - let transferSigner - - const doTransfer = async () => { - const { v, r, s } = await getSignatureForMetaTransaction(transferSigner, wallet.address, { - value, - destination, - data, - nonce, - }) - - return wallet.executeMetaTransaction(destination, value, data, v, r, s, { - from: submitter, - }) - } - - beforeEach(async () => { - // Transfer some funds to the wallet - await web3.eth.sendTransaction({ from: accounts[0], to: wallet.address, value }) - }) - - describe('when submitted by a non-signer', () => { - beforeEach(() => { - submitter = nonSigner - }) - - describe('when the nonce is valid', () => { - beforeEach(() => { - nonce = 0 - }) - - let res: any - describe('when signed by the signer', () => { - beforeEach(async () => { - transferSigner = signer - res = await doTransfer() - }) - - it('should execute the transaction', async () => { - assert.equal(await web3.eth.getBalance(destination), value) - }) - - it('should increment the nonce', async () => { - assertEqualBN(await wallet.nonce(), 1) - }) - - it('should emit the MetaTransactionExecution event', () => { - assertLogMatches2(res.logs[0], { - event: 'MetaTransactionExecution', - args: { - destination, - value, - data: null, - nonce: 0, - returnData: null, - }, - }) - }) - }) - - describe('when signed by a non-signer', () => { - it('should revert', async () => { - transferSigner = nonSigner - await assertTransactionRevertWithReason(doTransfer(), 'Invalid meta-transaction signer') - }) - }) - }) - - describe('when the nonce is invalid', () => { - beforeEach(() => { - nonce = 1 - }) - describe('when signed by the signer', () => { - beforeEach(() => { - transferSigner = signer - }) - it('should revert', async () => { - await assertTransactionRevertWithReason(doTransfer(), 'Invalid meta-transaction signer') - }) - }) - }) - }) - }) -}) diff --git a/packages/protocol/test/common/metatransactionwalletdeployer.ts b/packages/protocol/test/common/metatransactionwalletdeployer.ts deleted file mode 100644 index 7866974f5..000000000 --- a/packages/protocol/test/common/metatransactionwalletdeployer.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { - MetaTransactionWalletContract, - MetaTransactionWalletDeployerContract, - MetaTransactionWalletDeployerInstance, - MetaTransactionWalletInstance, - ProxyContract, -} from 'types' - -const MetaTransactionWalletDeployer: MetaTransactionWalletDeployerContract = artifacts.require( - 'MetaTransactionWalletDeployer' -) - -const MetaTransactionWallet: MetaTransactionWalletContract = - artifacts.require('MetaTransactionWallet') - -const Proxy: ProxyContract = artifacts.require('Proxy') - -contract('MetaTransactionWalletDeployer', (accounts: string[]) => { - let deployer: MetaTransactionWalletDeployerInstance - const valoraAccount = accounts[1] - - beforeEach(async () => { - deployer = await MetaTransactionWalletDeployer.new() - }) - - describe('#deploy', async () => { - let implementation: MetaTransactionWalletInstance - let deployRes - let walletDeployedEvent - - before(async () => { - implementation = await MetaTransactionWallet.new(true) - }) - - beforeEach(async () => { - // @ts-ignore - deployRes = await deployer.deploy( - valoraAccount, - implementation.address, - // @ts-ignore - implementation.contract.methods.initialize(valoraAccount).encodeABI() - ) - walletDeployedEvent = deployRes.logs.find((log) => log.event === 'WalletDeployed') - }) - - it('deploys a wallet', async () => { - assert.exists(walletDeployedEvent) - assert.equal(walletDeployedEvent.args.owner, valoraAccount) - assert.equal(walletDeployedEvent.args.implementation, implementation.address) - }) - - it('initializes the wallet with the correct signer', async () => { - const wallet = await MetaTransactionWallet.at(walletDeployedEvent.args.wallet) - assert.equal(await wallet.signer(), valoraAccount) - }) - - it('sets the the right proxy implementation', async () => { - const proxy = await Proxy.at(walletDeployedEvent.args.wallet) - assert.equal(await proxy._getImplementation(), implementation.address) - }) - - describe('when the external account already owns a wallet', async () => { - beforeEach(async () => { - await deployer.deploy( - valoraAccount, - implementation.address, - // @ts-ignore - implementation.contract.methods.initialize(valoraAccount).encodeABI() - ) - deployRes = await deployer.deploy( - valoraAccount, - implementation.address, - // @ts-ignore - implementation.contract.methods.initialize(valoraAccount).encodeABI() - ) - walletDeployedEvent = deployRes.logs.find((log) => log.event === 'WalletDeployed') - }) - - it('does redeploy', async () => { - assert.exists(walletDeployedEvent) - assert.equal(walletDeployedEvent.args.owner, valoraAccount) - assert.equal(walletDeployedEvent.args.implementation, implementation.address) - }) - }) - }) -}) diff --git a/packages/protocol/test/common/migration.ts b/packages/protocol/test/common/migration.ts deleted file mode 100644 index b4e1dd575..000000000 --- a/packages/protocol/test/common/migration.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { - assertContractsRegistered, - assertProxiesSet, - assertRegistryAddressesSet, -} from '@celo/protocol/lib/test-utils' -import { getDeployedProxiedContract } from '@celo/protocol/lib/web3-utils' -import { ContractPackage } from 'contractPackages' -import { ArtifactsSingleton } from '../../lib/artifactsSingleton' - -const getProxiedContract = async (contractName: string, contractPackage: ContractPackage) => { - const artifactsObject = ArtifactsSingleton.getInstance(contractPackage, artifacts) - /* tslint:disable-next-line */ - return await getDeployedProxiedContract(contractName, artifactsObject) -} - -const getContract = async ( - contractName: string, - type: string, - contractPackage: ContractPackage -) => { - // /* tslint:disable-next-line */ - const artifactsObject = ArtifactsSingleton.getInstance(contractPackage, artifacts) - - if (type === 'contract') { - /* tslint:disable-next-line */ - return await artifactsObject.require(contractName).deployed() - } - if (type === 'proxy') { - /* tslint:disable-next-line */ - return await artifactsObject.require(contractName + 'Proxy').deployed() - } -} - -contract('Migration', () => { - describe('Checking proxies', () => { - // https://github.com/celo-org/celo-monorepo/issues/10566 - it.skip('should have the proxy set up for all proxied contracts', async () => { - await assertProxiesSet(getContract) - }) - }) - - describe('Checking the registry', () => { - it('should have the correct entry in the registry for all contracts used by the registry', async () => { - await assertContractsRegistered(getProxiedContract) - }) - }) - - describe('Checking contracts that use the registry', () => { - it.skip('should have set the registry address properly in all contracts that use it', async () => { - await assertRegistryAddressesSet(getProxiedContract) - }) - }) -}) diff --git a/packages/protocol/test/common/proxy.ts b/packages/protocol/test/common/proxy.ts deleted file mode 100644 index d2e0dc8be..000000000 --- a/packages/protocol/test/common/proxy.ts +++ /dev/null @@ -1,279 +0,0 @@ -import { recoverFunds } from '@celo/protocol/lib/recover-funds' -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { - assertTransactionRevertWithReason, - expectBigNumberInRange, -} from '@celo/protocol/lib/test-utils' -import { BigNumber } from 'bignumber.js' -import { - FreezerContract, - GetSetV0Instance, - GetSetV1Instance, - GoldTokenContract, - HasInitializerInstance, - MsgSenderCheckInstance, - ProxyInstance, - RegistryContract, -} from 'types' - -const GetSetV0: Truffle.Contract = artifacts.require('GetSetV0') -const GetSetV1: Truffle.Contract = artifacts.require('GetSetV1') -const HasInitializer: Truffle.Contract = artifacts.require( - './contracts/HasInitializer.sol' -) -const MsgSenderCheck: Truffle.Contract = artifacts.require('MsgSenderCheck') -const Proxy: Truffle.Contract = artifacts.require('Proxy') - -contract('Proxy', (accounts: string[]) => { - let proxy: ProxyInstance - let getSet: GetSetV0Instance - let proxiedGetSet: GetSetV0Instance - - const owner = accounts[0] - - beforeEach(async () => { - proxy = await Proxy.new({ from: owner }) - getSet = await GetSetV0.new({ from: owner }) - proxiedGetSet = await GetSetV0.at(proxy.address) - }) - - describe('#getOwner', () => { - it('gets the address of the owner', async () => { - const res = await proxy._getOwner() - assert.equal(res, owner) - }) - }) - - describe('#setImplementation', () => { - it('should allow the owner to set an implementation', async () => { - await proxy._setImplementation(getSet.address) - const res = await proxy._getImplementation() - assert.equal(res, getSet.address) - }) - - it('should not allow a non-owner to set an implementation', async () => { - await assertTransactionRevertWithReason( - proxy._setImplementation(getSet.address, { from: accounts[1] }), - 'sender was not owner' - ) - }) - - it('should allow the implementation to be updated', async () => { - await proxy._setImplementation(getSet.address) - - const getSet1: GetSetV1Instance = await GetSetV1.new() - - await proxy._setImplementation(getSet1.address) - const res = await proxy._getImplementation() - assert.equal(res, getSet1.address) - }) - - it('should not affect logic-related storage', async () => { - await proxy._setImplementation(getSet.address) - await proxiedGetSet.set(42) - - const getSet1: GetSetV1Instance = await GetSetV1.new() - await proxy._setImplementation(getSet1.address) - - const res = await proxiedGetSet.get() - assert.equal(res.toNumber(), 42) - }) - - it('should emit an event', async () => { - const response = await proxy._setImplementation(getSet.address) - const events = response.logs - assert.equal(events.length, 1) - assert.equal(events[0].event, 'ImplementationSet') - }) - }) - - describe('#setAndInitializeImplementation', () => { - let hasInitializer: HasInitializerInstance - let proxiedHasInitializer: HasInitializerInstance - const initializeData = (x: string | number) => { - // @ts-ignore - const initializeAbi = HasInitializer.abi.find( - (abi: any) => abi.type === 'function' && abi.name === 'initialize' - ) - - return web3.eth.abi.encodeFunctionCall(initializeAbi, [x]) - } - - beforeEach(async () => { - hasInitializer = await HasInitializer.new({ from: owner }) - proxiedHasInitializer = await HasInitializer.at(proxy.address) - }) - - it('should allow the owner to set an implementation', async () => { - await proxy._setAndInitializeImplementation(hasInitializer.address, initializeData(42)) - - const res = await proxy._getImplementation() - assert.equal(res, hasInitializer.address) - }) - - it('should initialize data needed by the implementation', async () => { - await proxy._setAndInitializeImplementation(hasInitializer.address, initializeData(42)) - - const res = await proxiedHasInitializer.x() - assert.equal(res.toNumber(), 42) - }) - - it('should emit an event', async () => { - const response = await proxy._setAndInitializeImplementation( - hasInitializer.address, - initializeData(owner) - ) - const events = response.logs - assert.equal(events.length, 1) - assert.equal(events[0].event, 'ImplementationSet') - }) - - it('should not allow to call a non contract address', async () => - assertTransactionRevertWithReason( - proxy._setAndInitializeImplementation(accounts[1], initializeData(42), { - from: accounts[1], - }), - 'sender was not owner' - )) - - it('should not allow a non-owner to set an implementation', async () => - assertTransactionRevertWithReason( - proxy._setAndInitializeImplementation(hasInitializer.address, initializeData(42), { - from: accounts[1], - }), - 'sender was not owner' - )) - - it('should not allow for a call to `initialize` after initialization', async () => { - await proxy._setAndInitializeImplementation(hasInitializer.address, initializeData(42)) - await assertTransactionRevertWithReason( - proxiedHasInitializer.initialize(43), - 'contract already initialized' - ) - }) - }) - - describe('#transferOwnership', () => { - it('should allow the owner to transfer ownership', async () => { - await proxy._transferOwnership(accounts[2]) - const newOwner = await proxy._getOwner() - assert.equal(newOwner, accounts[2]) - }) - - it('should not allow a non-owner to transfer ownership', async () => { - await assertTransactionRevertWithReason( - proxy._transferOwnership(accounts[2], { from: accounts[1] }), - 'sender was not owner' - ) - }) - - it('should emit an event', async () => { - const response = await proxy._transferOwnership(accounts[2]) - const events = response.logs - assert.equal(events.length, 1) - assert.equal(events[0].event, 'OwnerSet') - }) - - describe('after transferring ownership', () => { - let getSet1: GetSetV1Instance - const newOwner: string = accounts[1] - - beforeEach(async () => { - getSet1 = await GetSetV1.new({ from: owner }) - await proxy._transferOwnership(newOwner) - }) - - it('should allow the new owner to perform ownerOnly actions', async () => { - await proxy._setImplementation(getSet1.address, { from: newOwner }) - }) - - it('should not allow the previous owner to perform onlyOwner actions', async () => { - await assertTransactionRevertWithReason( - proxy._setImplementation(getSet1.address), - 'sender was not owner' - ) - }) - }) - }) - - describe('fallback', () => { - beforeEach(async () => { - await proxy._setImplementation(getSet.address) - }) - - it('should call functions from the target contract', async () => { - await proxiedGetSet.set(42) - const res = await proxiedGetSet.get() - assert.equal(res.toNumber(), 42) - }) - - it('should access public variables from the target contract', async () => { - await proxiedGetSet.set(42) - const res = await proxiedGetSet.x() - assert.equal(res.toNumber(), 42) - }) - - it('should not affect the storage of the target contract', async () => { - await proxiedGetSet.set(42) - const res = await getSet.get() - assert.equal(res.toNumber(), 0) - }) - - it('should preserve msg.sender', async () => { - const msgSenderCheck: MsgSenderCheckInstance = await MsgSenderCheck.new() - const proxiedMsgSenderCheck = await MsgSenderCheck.at(proxy.address) - await proxy._setImplementation(msgSenderCheck.address) - - await proxiedMsgSenderCheck.checkMsgSender(owner) - }) - - describe('after changing the implementation', () => { - let getSet1: GetSetV1Instance - let proxiedGetSet1: GetSetV1Instance - - beforeEach(async () => { - getSet1 = await GetSetV1.new({ from: owner }) - proxiedGetSet1 = await GetSetV1.at(proxy.address) - await proxy._setImplementation(getSet1.address) - }) - - it('should be able to proxy to the new contract', async () => { - await proxiedGetSet1.set(42, "DON'T PANIC") - const res = await proxiedGetSet1.get() - assert.equal(res[0].toNumber(), 42) - assert.equal(res[1], "DON'T PANIC") - }) - }) - }) - - it('recovers funds from an incorrectly intialized implementation', async () => { - const Freezer: FreezerContract = artifacts.require('Freezer') - const GoldToken: GoldTokenContract = artifacts.require('GoldToken') - // @ts-ignore - GoldToken.numberFormat = 'BigNumber' - const Registry: RegistryContract = artifacts.require('Registry') - - const freezer = await Freezer.new(true) - const goldToken = await GoldToken.new(true) - const registry = await Registry.new(true) - await registry.setAddressFor(CeloContractName.Freezer, freezer.address) - await goldToken.initialize(registry.address) - - const amount = new BigNumber(10) - const initialBalance = new BigNumber(await goldToken.balanceOf(owner)) - await goldToken.transfer(proxy.address, amount) - - await proxy._setImplementation(getSet.address) - - const ownerBalance = await goldToken.balanceOf(owner) - - expectBigNumberInRange(ownerBalance, initialBalance.minus(amount)) - const proxyBalance = await web3.eth.getBalance(proxy.address) - assert(proxyBalance === amount.toString()) - - await recoverFunds(proxy.address, owner) - const ownerBalance2 = await goldToken.balanceOf(owner) - assert((await web3.eth.getBalance(proxy.address)) === '0') - expectBigNumberInRange(ownerBalance2, initialBalance) - }) -}) diff --git a/packages/protocol/test/common/uniswapfeehandlerseller.ts b/packages/protocol/test/common/uniswapfeehandlerseller.ts deleted file mode 100644 index 0c0aca7d5..000000000 --- a/packages/protocol/test/common/uniswapfeehandlerseller.ts +++ /dev/null @@ -1,103 +0,0 @@ -// /* tslint:disable */ - -// TODO remove magic numbers -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { assertTransactionRevertWithReason } from '@celo/protocol/lib/test-utils' -import { - GoldTokenContract, - GoldTokenInstance, - RegistryContract, - RegistryInstance, - UniswapFeeHandlerSellerContract, - UniswapFeeHandlerSellerInstance, -} from 'types' - -const UniswapFeeHandlerSeller: UniswapFeeHandlerSellerContract = - artifacts.require('UniswapFeeHandlerSeller') - -const GoldToken: GoldTokenContract = artifacts.require('GoldToken') -const Registry: RegistryContract = artifacts.require('Registry') - -contract('UniswapFeeHandlerSeller', (accounts: string[]) => { - let uniswapFeeHandlerSeller: UniswapFeeHandlerSellerInstance - let goldToken: GoldTokenInstance - let registry: RegistryInstance - - const addressA = '0xFA907Ed32fC6Ca20408214C0DC8734403738AbDb' - const addressB = '0x61eb0a82C8802090b61381853e7Ec34b985e9b85' - const addressC = '0xb7c771B22A983e19fE7aCAB574F7dF5A6C65cAB1' - const addressD = '0x866284bd3946882CFc23e2F14942f5c293fb5742' - - const user = accounts[1] - - beforeEach(async () => { - registry = await Registry.new(true) - - goldToken = await GoldToken.new(true) - await goldToken.initialize(registry.address) - await registry.setAddressFor(CeloContractName.GoldToken, goldToken.address) - - uniswapFeeHandlerSeller = await UniswapFeeHandlerSeller.new(true) - }) - - describe('#setRouter()', () => { - it('sets pool for exchange', async () => { - await uniswapFeeHandlerSeller.setRouter(addressA, addressB) - assert((await uniswapFeeHandlerSeller.getRoutersForToken(addressA))[0], addressB) - }) - - it('only owner can setRouter', async () => { - await assertTransactionRevertWithReason( - uniswapFeeHandlerSeller.setRouter(addressA, addressB, { from: user }), - 'Ownable: caller is not the owner' - ) - }) - - it("Can't set address zero", async () => { - await assertTransactionRevertWithReason( - uniswapFeeHandlerSeller.setRouter(addressA, '0x0000000000000000000000000000000000000000'), - "Router can't be address zero." - ) - }) - - it("Can't add more than 4 routers", async () => { - await uniswapFeeHandlerSeller.setRouter(addressA, addressB) - await uniswapFeeHandlerSeller.setRouter(addressA, accounts[1]) - await uniswapFeeHandlerSeller.setRouter(addressA, accounts[2]) - await assertTransactionRevertWithReason( - uniswapFeeHandlerSeller.setRouter(addressA, accounts[4]), - 'Max number of routers reached.' - ) - }) - }) - - describe('#removeRouter()', () => { - beforeEach(async () => { - await uniswapFeeHandlerSeller.setRouter(addressA, addressB) - }) - - it('removes a token', async () => { - await uniswapFeeHandlerSeller.removeRouter(addressA, addressB) - expect((await uniswapFeeHandlerSeller.getRoutersForToken(addressA)).toString()).to.equal( - [].toString() - ) - }) - - it('removes when list is big', async () => { - await uniswapFeeHandlerSeller.setRouter(addressA, addressD) - await uniswapFeeHandlerSeller.setRouter(addressA, addressC) - // list for token should be [uniswap, exchange, stabletoken] - await uniswapFeeHandlerSeller.removeRouter(addressA, addressD) - expect((await uniswapFeeHandlerSeller.getRoutersForToken(addressA)).toString()).to.equal( - [addressB, addressC].toString() - ) - }) - - it('only owner can removeRouter', async () => { - await assertTransactionRevertWithReason( - uniswapFeeHandlerSeller.removeRouter(addressA, addressB, { from: user }), - 'Ownable: caller is not the owner.' - ) - }) - }) -}) diff --git a/packages/protocol/test/compatibility/ast-code.ts b/packages/protocol/test/compatibility/ast-code.ts deleted file mode 100644 index 12d619602..000000000 --- a/packages/protocol/test/compatibility/ast-code.ts +++ /dev/null @@ -1,136 +0,0 @@ -import { reportASTIncompatibilities } from '@celo/protocol/lib/compatibility/ast-code' -import { - Change, - DeployedBytecodeChange, - MethodAddedChange, - MethodMutabilityChange, - MethodRemovedChange, - MethodReturnChange, - MethodVisibilityChange, - NewContractChange, -} from '@celo/protocol/lib/compatibility/change' -import { getTestArtifacts } from '@celo/protocol/test/compatibility/common' -import { assert } from 'chai' - -const testCases = { - original: getTestArtifacts('original'), - original_copy: getTestArtifacts('original_copy'), - inserted_constant: getTestArtifacts('inserted_constant'), - added_methods_and_contracts: getTestArtifacts('added_methods_and_contracts'), - metadata_changed: getTestArtifacts('metadata_changed'), - big_original: getTestArtifacts('big_original'), - big_original_modified: getTestArtifacts('big_original_modified'), -} - -// @ts-ignore -const comp = (c1: Change, c2: Change): number => { - const v1 = JSON.stringify(c1) - const v2 = JSON.stringify(c2) - if (v1 === v2) { - return 0 - } - return v1 < v2 ? 1 : -1 -} - -describe('#reportASTIncompatibilities()', () => { - describe('when the contracts are the same', () => { - it('reports no changes', () => { - const report = reportASTIncompatibilities(testCases.original, [testCases.original_copy]) - assert.isEmpty(report.getChanges()) - }) - }) - - describe('when only metadata has changed', () => { - it('reports no changes', () => { - const report = reportASTIncompatibilities(testCases.original, [testCases.metadata_changed]) - assert.isEmpty(report.getChanges()) - }) - }) - - describe('when a contract storage is changed', () => { - it('reports only bytecode changes', () => { - const report = reportASTIncompatibilities(testCases.original, [testCases.inserted_constant]) - const expected = [new DeployedBytecodeChange('TestContract')] - assert.deepEqual(report.getChanges(), expected) - }) - }) - - describe('when a contract and methods are added', () => { - it('reports proper changes', () => { - const report = reportASTIncompatibilities(testCases.original, [ - testCases.added_methods_and_contracts, - ]) - const expected = [ - new NewContractChange('TestContractNew'), - new DeployedBytecodeChange('TestContract'), - new MethodAddedChange('TestContract', 'newMethod1(uint256)'), - new MethodAddedChange('TestContract', 'newMethod2(uint256)'), - ].sort(comp) - const changes = report.getChanges() - changes.sort(comp) - assert.deepEqual(changes, expected) - }) - }) - - describe('when methods are removed', () => { - it('reports proper changes', () => { - const report = reportASTIncompatibilities(testCases.added_methods_and_contracts, [ - testCases.original, - ]) - const expected = [ - new DeployedBytecodeChange('TestContract'), - new MethodRemovedChange('TestContract', 'newMethod1(uint256)'), - new MethodRemovedChange('TestContract', 'newMethod2(uint256)'), - ].sort(comp) - const changes = report.getChanges() - changes.sort(comp) - assert.deepEqual(changes, expected) - }) - }) - - describe('when many changes are made', () => { - it('reports proper changes', () => { - const report = reportASTIncompatibilities(testCases.big_original, [ - testCases.big_original_modified, - ]) - const expected = [ - new NewContractChange('NewContract'), - new DeployedBytecodeChange('ImplementationChangeContract'), - new DeployedBytecodeChange('MethodsAddedContract'), - new MethodAddedChange('MethodsAddedContract', 'newMethod1()'), - new MethodAddedChange('MethodsAddedContract', 'newMethod2(uint256)'), - new DeployedBytecodeChange('MethodsRemovedContract'), - new MethodRemovedChange('MethodsRemovedContract', 'someMethod1(uint256)'), - new MethodRemovedChange('MethodsRemovedContract', 'someMethod2(uint256)'), - new DeployedBytecodeChange('MethodsModifiedContract'), - new MethodVisibilityChange( - 'MethodsModifiedContract', - 'someMethod1(uint256)', - 'external', - 'public' - ), - new MethodMutabilityChange( - 'MethodsModifiedContract', - 'someMethod2(uint256)', - 'pure', - 'view' - ), - new MethodMutabilityChange( - 'MethodsModifiedContract', - 'someMethod4(uint256)', - 'payable', - 'nonpayable' - ), - new MethodReturnChange( - 'MethodsModifiedContract', - 'someMethod3(uint256,string)', - 'uint256, memory string', - 'uint256, memory string, uint256' - ), - ].sort(comp) - const changes = report.getChanges() - changes.sort(comp) - assert.deepEqual(changes, expected) - }) - }) -}) diff --git a/packages/protocol/test/compatibility/ast-layout.ts b/packages/protocol/test/compatibility/ast-layout.ts deleted file mode 100644 index f36f78864..000000000 --- a/packages/protocol/test/compatibility/ast-layout.ts +++ /dev/null @@ -1,324 +0,0 @@ -import { reportLayoutIncompatibilities } from '@celo/protocol/lib/compatibility/ast-layout' -import { getTestArtifacts } from '@celo/protocol/test/compatibility/common' -import { assert } from 'chai' - -const testCases = { - original: getTestArtifacts('original'), - inserted_constant: getTestArtifacts('inserted_constant'), - appended: getTestArtifacts('appended'), - inserted: getTestArtifacts('inserted'), - appended_in_parent: getTestArtifacts('appended_in_parent'), - removed: getTestArtifacts('removed'), - typechange: getTestArtifacts('typechange'), - typechange_in_struct: getTestArtifacts('typechange_in_struct'), - typechange_in_parent: getTestArtifacts('typechange_in_parent'), - typechange_in_library_struct: getTestArtifacts('typechange_in_library_struct'), - removed_from_struct: getTestArtifacts('removed_from_struct'), - removed_from_parent: getTestArtifacts('removed_from_parent'), - inserted_in_struct: getTestArtifacts('inserted_in_struct'), - inserted_in_library_struct: getTestArtifacts('inserted_in_library_struct'), - removed_from_library_struct: getTestArtifacts('removed_from_library_struct'), - - original_complex: getTestArtifacts('original_complex'), - shorter_fixed_array: getTestArtifacts('shorter_fixed_array'), - longer_fixed_array: getTestArtifacts('longer_fixed_array'), - fixed_to_dynamic_array: getTestArtifacts('fixed_to_dynamic_array'), - dynamic_to_fixed_array: getTestArtifacts('dynamic_to_fixed_array'), - mapping_source_changed: getTestArtifacts('mapping_source_changed'), - internal_mapping_source_changed: getTestArtifacts('internal_mapping_source_changed'), - mapping_target_changed: getTestArtifacts('mapping_target_changed'), - - original_struct_in_mapping: getTestArtifacts('original_struct_in_mapping'), - inserted_in_struct_mapping: getTestArtifacts('inserted_in_struct_mapping'), - inserted_in_library_struct_mapping: getTestArtifacts('inserted_in_library_struct_mapping'), - deprecated_prefixed_in_library_struct_mapping: getTestArtifacts( - 'deprecated_prefixed_in_library_struct_mapping' - ), - deprecated_prefixed_in_struct: getTestArtifacts('deprecated_prefixed_in_struct'), - deprecated_prefixed_variable: getTestArtifacts('deprecated_prefixed_variable'), -} - -const assertCompatible = (report) => { - assert.isTrue(report.every((contractReport) => contractReport.compatible)) -} - -const assertNotCompatible = (report) => { - assert.isFalse(report.every((contractReport) => contractReport.compatible)) -} - -const selectReportFor = (report, contractName) => { - return report.find((contractReport) => contractReport.contract === contractName) -} - -/* Checks that expected errors were reported for a contract. - * @param report The list of CompatibilityInfo's to check. - * @param contractName The name of the contract to check. - * @param expectedMatches The regular expressions that each successive error for - * `contractName` should match. - */ -const assertContractErrorsMatch = (report, contractName, expectedMatches) => { - const contractReport = selectReportFor(report, contractName) - assert.equal(contractReport.errors.length, 1) - - contractReport.errors.forEach((error, i) => { - assert.match(error, expectedMatches[i]) - }) -} - -describe('#reportLayoutIncompatibilities()', () => { - describe('when the contracts are the same', () => { - it('reports no incompatibilities', () => { - const report = reportLayoutIncompatibilities(testCases.original, [testCases.original]) - assertCompatible(report) - }) - }) - - describe('when a constant is inserted in a contract', () => { - it('reports no incompatibilities', () => { - const report = reportLayoutIncompatibilities(testCases.original, [ - testCases.inserted_constant, - ]) - assertCompatible(report) - }) - }) - - describe('when a variable is appended in a contract', () => { - it('reports no incompatibilities', () => { - const report = reportLayoutIncompatibilities(testCases.original, [testCases.appended]) - assertCompatible(report) - }) - }) - - describe('when a variable is inserted in a contract', () => { - it('reports an inserted variable', () => { - const report = reportLayoutIncompatibilities(testCases.original, [testCases.inserted]) - assertNotCompatible(report) - assertContractErrorsMatch(report, 'TestContract', [/inserted/]) - }) - }) - - describe('when a variable is appended in a parent contract', () => { - it('reports an inserted variable', () => { - const report = reportLayoutIncompatibilities(testCases.original, [ - testCases.appended_in_parent, - ]) - assertNotCompatible(report) - assertContractErrorsMatch(report, 'TestContract', [/inserted/]) - }) - }) - - describe('when a variable is removed in a contract', () => { - it('reports a removed variable', () => { - const report = reportLayoutIncompatibilities(testCases.original, [testCases.removed]) - assertNotCompatible(report) - assertContractErrorsMatch(report, 'TestContract', [/removed/]) - }) - }) - - describe('when a variable is removed in a parent contract', () => { - it('reports a removed variable', () => { - const report = reportLayoutIncompatibilities(testCases.original, [ - testCases.removed_from_parent, - ]) - assertNotCompatible(report) - assertContractErrorsMatch(report, 'TestContract', [/removed/]) - }) - }) - - describe(`when a variable's type changes in a contract`, () => { - it('reports a typechanged variable', () => { - const report = reportLayoutIncompatibilities(testCases.original, [testCases.typechange]) - assertNotCompatible(report) - assertContractErrorsMatch(report, 'TestContract', [/had type/]) - }) - }) - - describe(`when a variable's type changes in a parent contract`, () => { - it('reports a typechanged variable', () => { - const report = reportLayoutIncompatibilities(testCases.original, [ - testCases.typechange_in_parent, - ]) - assertNotCompatible(report) - assertContractErrorsMatch(report, 'TestContract', [/had type/]) - }) - }) - - describe('when a field is added to a struct in mapping', () => { - it('reports no incompatibilities', () => { - const report = reportLayoutIncompatibilities(testCases.original_struct_in_mapping, [ - testCases.inserted_in_struct_mapping, - ]) - assertCompatible(report) - }) - }) - - describe('when a field is added to a library struct in mapping', () => { - it('reports no incompatibilities', () => { - const report = reportLayoutIncompatibilities(testCases.original_struct_in_mapping, [ - testCases.inserted_in_library_struct_mapping, - ]) - assertCompatible(report) - }) - }) - - describe('when a field is prefixed with deprecated to a library struct in mapping', () => { - it('reports no incompatibilities', () => { - const report = reportLayoutIncompatibilities(testCases.original_struct_in_mapping, [ - testCases.deprecated_prefixed_in_library_struct_mapping, - ]) - assertCompatible(report) - }) - }) - - describe('when a field is prefixed with deprecated to struct variable', () => { - it('reports no incompatibilities', () => { - const report = reportLayoutIncompatibilities(testCases.original, [ - testCases.deprecated_prefixed_in_struct, - ]) - assertCompatible(report) - }) - }) - - describe('when a variable is prefixed with deprecated', () => { - it('reports no incompatibilities', () => { - const report = reportLayoutIncompatibilities(testCases.original, [ - testCases.deprecated_prefixed_variable, - ]) - assertCompatible(report) - }) - }) - - describe('when a field is added to a struct', () => { - it('reports a struct change', () => { - const report = reportLayoutIncompatibilities(testCases.original, [ - testCases.inserted_in_struct, - ]) - assertNotCompatible(report) - assertContractErrorsMatch(report, 'TestContract', [/struct.*changed/]) - }) - }) - - describe('when a field changes type in a struct', () => { - it('reports a struct change', () => { - const report = reportLayoutIncompatibilities(testCases.original, [ - testCases.typechange_in_struct, - ]) - assertNotCompatible(report) - assertContractErrorsMatch(report, 'TestContract', [/struct.*changed/]) - }) - }) - - describe('when a field changes type in a library struct', () => { - it('reports a struct change', () => { - const report = reportLayoutIncompatibilities(testCases.original, [ - testCases.typechange_in_library_struct, - ]) - assertNotCompatible(report) - assertContractErrorsMatch(report, 'TestContract', [/struct.*changed/]) - }) - }) - - describe('when a field is removed from a struct', () => { - it('reports a struct change', () => { - const report = reportLayoutIncompatibilities(testCases.original, [ - testCases.removed_from_struct, - ]) - assertNotCompatible(report) - assertContractErrorsMatch(report, 'TestContract', [/struct.*changed/]) - }) - }) - - describe('when a field is removed from a library struct', () => { - it('reports a struct change', () => { - const report = reportLayoutIncompatibilities(testCases.original, [ - testCases.removed_from_library_struct, - ]) - assertNotCompatible(report) - assertContractErrorsMatch(report, 'TestContract', [/struct.*changed/]) - }) - }) - - describe('when a field is inserted in a library struct', () => { - it('reports a struct change', () => { - const report = reportLayoutIncompatibilities(testCases.original, [ - testCases.inserted_in_library_struct, - ]) - assertNotCompatible(report) - assertContractErrorsMatch(report, 'TestContract', [/struct.*changed/]) - }) - }) - - describe('when a fixed array has length increased', () => { - it('reports a typechanged variable', () => { - const report = reportLayoutIncompatibilities(testCases.original_complex, [ - testCases.longer_fixed_array, - ]) - assertNotCompatible(report) - assertContractErrorsMatch(report, 'TestContract', [/had type/]) - }) - }) - - describe('when a fixed array has length decreased', () => { - it('reports a typechanged variable', () => { - const report = reportLayoutIncompatibilities(testCases.original_complex, [ - testCases.shorter_fixed_array, - ]) - assertNotCompatible(report) - assertContractErrorsMatch(report, 'TestContract', [/had type/]) - }) - }) - - describe('when a fixed array becomes dynamic', () => { - it('reports a typechanged variable', () => { - const report = reportLayoutIncompatibilities(testCases.original_complex, [ - testCases.fixed_to_dynamic_array, - ]) - assertNotCompatible(report) - assertContractErrorsMatch(report, 'TestContract', [/had type/]) - }) - }) - - describe('when a dynamic array becomes fixed', () => { - it('reports a typechanged variable', () => { - const report = reportLayoutIncompatibilities(testCases.original_complex, [ - testCases.dynamic_to_fixed_array, - ]) - assertNotCompatible(report) - assertContractErrorsMatch(report, 'TestContract', [/had type/]) - }) - }) - - // TODO(m-chrzan): @openzeppelin/upgrades erases information about mapping key - // types before generating a layout diff. We might want to patch this behavior - // so that this sort of type change is identified as a backwards - // incompatibility. - describe.skip('when the source of a mapping changes', () => { - it('reports a typechanged variable', () => { - const report = reportLayoutIncompatibilities(testCases.original_complex, [ - testCases.mapping_source_changed, - ]) - assertNotCompatible(report) - assertContractErrorsMatch(report, 'TestContract', [/had type/]) - }) - }) - - describe.skip('when the source of a nested mapping changes', () => { - it('reports a typechanged variable', () => { - const report = reportLayoutIncompatibilities(testCases.original_complex, [ - testCases.internal_mapping_source_changed, - ]) - assertNotCompatible(report) - assertContractErrorsMatch(report, 'TestContract', [/had type/]) - }) - }) - - describe('when the target of a mapping changes', () => { - it('reports a typechanged variable', () => { - const report = reportLayoutIncompatibilities(testCases.original_complex, [ - testCases.mapping_target_changed, - ]) - assertNotCompatible(report) - assertContractErrorsMatch(report, 'TestContract', [/had type/]) - }) - }) -}) diff --git a/packages/protocol/test/compatibility/ast-version.ts b/packages/protocol/test/compatibility/ast-version.ts deleted file mode 100644 index 98de28072..000000000 --- a/packages/protocol/test/compatibility/ast-version.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { getContractVersion } from '@celo/protocol/lib/compatibility/ast-version' -import { DEFAULT_VERSION_STRING } from '@celo/protocol/lib/compatibility/version' -import { getTestArtifacts } from '@celo/protocol/test/compatibility/common' -import { assert } from 'chai' - -const testCases = { - original: getTestArtifacts('original'), - versioned: getTestArtifacts('versioned'), -} - -describe('#getContractVersion()', () => { - describe('when the contract implements getVersionNumber()', () => { - it('returns the correct version number', async () => { - const version = await getContractVersion( - testCases.versioned.getArtifactByName('TestContract') - ) - assert.equal(version.toString(), '1.2.3.4') - }) - }) - - describe('when the contract does not implement getVersionNumber()', () => { - it('returns the default version number', async () => { - const version = await getContractVersion(testCases.original.getArtifactByName('TestContract')) - assert.equal(version.toString(), DEFAULT_VERSION_STRING) - }) - }) -}) diff --git a/packages/protocol/test/compatibility/common.ts b/packages/protocol/test/compatibility/common.ts deleted file mode 100644 index 663d6ec24..000000000 --- a/packages/protocol/test/compatibility/common.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { getBuildArtifacts } from '@openzeppelin/upgrades' -import { execSync } from 'child_process' -import fs from 'fs' -import path from 'path' - -// Measured in millis -const recompileThresholdTime = 1000 * 60 * 60 * 24 // One day - -const ROOT_DIR = path.normalize(path.join(__dirname, '../../')) - -function exec(cmd: string) { - return execSync(cmd, { cwd: ROOT_DIR, stdio: 'inherit' }) -} - -// Return the latest modification time of a file in the given directory -function getLatestUpdateTime(dir) { - if (!fs.existsSync(dir)) { - return 0 - } - const stat = fs.statSync(dir) - if (!stat.isDirectory) { - throw new Error(`Expected ${dir} to be a directory`) - } - return Math.max(...fs.readdirSync(dir).map((f) => fs.statSync(`${dir}/${f}`).mtimeMs)) -} - -function needsCompiling(src: string, build: string): boolean { - const srcTime = getLatestUpdateTime(src) - const buildTime = getLatestUpdateTime(build) - if (buildTime === 0) { - // Build folder is not present - return true - } - if (srcTime > buildTime) { - // Source was updated - return true - } - if (Date.now() - buildTime > recompileThresholdTime) { - // Build is too old - return true - } - return false -} - -export function getTestArtifacts(caseName: string) { - const back = './test/resources/compatibility' - const srcDirectory = `${back}/contracts_${caseName}` - const buildDirectory = `${back}/build/b_${caseName}` - - if (needsCompiling(srcDirectory, buildDirectory)) { - // We force all contracts compiled from the same source folder - // To minimize differences in the artifact files - const tmpSrcDirectory = `${back}/build/src` - // Clean folders - exec(`rm -rf ${tmpSrcDirectory}`) - exec(`rm -rf ${buildDirectory}`) - exec(`mkdir -p ./${tmpSrcDirectory}`) - // Copy the contracts source code to the src folder - exec(`cp -r ./${srcDirectory}/* ./${tmpSrcDirectory}`) - - exec( - `yarn run --silent truffle compile --all --contracts_directory=${tmpSrcDirectory} --contracts_build_directory=${buildDirectory}` - ) - } - return getBuildArtifacts(`${buildDirectory}`) -} diff --git a/packages/protocol/test/compatibility/library-linking.ts b/packages/protocol/test/compatibility/library-linking.ts deleted file mode 100644 index 3e5f5b4ec..000000000 --- a/packages/protocol/test/compatibility/library-linking.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { assert } from 'chai' - -import { reportASTIncompatibilities } from '@celo/protocol/lib/compatibility/ast-code' -import { reportLibraryLinkingIncompatibilities } from '@celo/protocol/lib/compatibility/library-linking' -import { getTestArtifacts } from '@celo/protocol/test/compatibility/common' - -const testCases = { - linked_libraries: getTestArtifacts('linked_libraries'), - linked_libraries_upgraded_lib: getTestArtifacts('linked_libraries_upgraded_lib'), -} - -describe('reportLibraryLinkingIncompatibilities', () => { - it('detects when a linked library has changed', () => { - const codeReport = reportASTIncompatibilities(testCases.linked_libraries, [ - testCases.linked_libraries_upgraded_lib, - ]) - const libraryLinksReport = reportLibraryLinkingIncompatibilities( - { - LinkedLibrary1: ['TestContract'], - LinkedLibrary2: ['TestContract'], - LinkedLibrary3: ['LinkedLibrary2'], - }, - codeReport - ) - assert.equal(libraryLinksReport.length, 2) - - const library2Change = libraryLinksReport.find( - (change) => change.getContract() === 'LinkedLibrary2' - ) - assert.isDefined(library2Change) - assert.equal(library2Change.getDependency(), 'LinkedLibrary3') - - const contractChange = libraryLinksReport.find( - (change) => change.getContract() === 'TestContract' - ) - assert.isDefined(contractChange) - assert.equal(contractChange.getDependency(), 'LinkedLibrary2') - }) -}) diff --git a/packages/protocol/test/compatibility/verify-bytecode.ts b/packages/protocol/test/compatibility/verify-bytecode.ts deleted file mode 100644 index e69c64755..000000000 --- a/packages/protocol/test/compatibility/verify-bytecode.ts +++ /dev/null @@ -1,377 +0,0 @@ -import { - LibraryAddresses, - LibraryLinks, - LibraryPositions, - linkLibraries, -} from '@celo/protocol/lib/bytecode' -import { Artifact } from '@celo/protocol/lib/compatibility/internal' -import { verifyBytecodes } from '@celo/protocol/lib/compatibility/verify-bytecode' -import { assertThrowsAsync } from '@celo/protocol/lib/test-utils' -import { getTestArtifacts } from '@celo/protocol/test/compatibility/common' -import { NULL_ADDRESS } from '@celo/utils/lib/address' -import { assert } from 'chai' -import { RegistryInstance } from 'types' - -import truffleContract = require('@truffle/contract') - -const Registry = artifacts.require('Registry') -const Proxy = artifacts.require('Proxy') - -const makeTruffleContract = (artifact: Artifact) => { - const Contract = truffleContract({ - abi: artifact.abi, - unlinked_binary: artifact.bytecode, - }) - Contract.setProvider(web3.currentProvider) - Contract.setNetwork('development') - - return Contract -} - -const deployProxiedContract = async (Contract: any, from: string) => { - const proxy = await Proxy.new() - const contract = await Contract.new({ from }) - await proxy._setImplementation(contract.address) - return Contract.at(proxy.address) -} - -contract('', (accounts) => { - const buildArtifacts = getTestArtifacts('linked_libraries') - const upgradedLibBuildArtifacts = getTestArtifacts('linked_libraries_upgraded_lib') - const upgradedContractBuildArtifacts = getTestArtifacts('linked_libraries_upgraded_contract') - const artifact = buildArtifacts.getArtifactByName('TestContract') - - const TestContract = makeTruffleContract(buildArtifacts.getArtifactByName('TestContract')) - const LinkedLibrary1 = makeTruffleContract(buildArtifacts.getArtifactByName('LinkedLibrary1')) - const LinkedLibrary2 = makeTruffleContract(buildArtifacts.getArtifactByName('LinkedLibrary2')) - const LinkedLibrary3 = makeTruffleContract(buildArtifacts.getArtifactByName('LinkedLibrary3')) - - describe('LibraryPositions()', () => { - it('collects the right number of positions for each library', () => { - const positions = new LibraryPositions(artifact.deployedBytecode) - assert.equal(positions.positions['LinkedLibrary1'].length, 2) - assert.equal(positions.positions['LinkedLibrary2'].length, 2) - }) - }) - - describe('#LibraryAddresses.collect()', () => { - describe('when libraries are linked correctly', () => { - it('collects the correct addresses', () => { - const positions = new LibraryPositions(artifact.deployedBytecode) - const links: LibraryLinks = { - LinkedLibrary1: '0000000000000000000000000000000000000001', - LinkedLibrary2: '0000000000000000000000000000000000000002', - } - const linkedBytecode = linkLibraries(artifact.deployedBytecode, links) - const addresses = new LibraryAddresses() - addresses.collect(linkedBytecode, positions) - - assert.equal( - addresses.addresses['LinkedLibrary1'], - '0000000000000000000000000000000000000001' - ) - assert.equal( - addresses.addresses['LinkedLibrary2'], - '0000000000000000000000000000000000000002' - ) - }) - }) - - describe('when libraries are not linked correctly', () => { - it('detects incorrect linking', () => { - const positions = new LibraryPositions(artifact.deployedBytecode) - const links: LibraryLinks = { - LinkedLibrary1: '0000000000000000000000000000000000000001', - LinkedLibrary2: '0000000000000000000000000000000000000002', - } - const linkedBytecode = linkLibraries(artifact.deployedBytecode, links) - const incorrectBytecode = - linkedBytecode.slice(0, positions.positions['LinkedLibrary1'][0] - 1) + - '0000000000000000000000000000000000000003' + - linkedBytecode.slice( - positions.positions['LinkedLibrary1'][0] - 1 + 40, - linkedBytecode.length - ) - - assert.throws(() => { - new LibraryAddresses().collect(incorrectBytecode, positions) - }) - }) - }) - }) - - describe('on a test contract deployment', () => { - let registry: RegistryInstance - let library1 - let library2 - let library3 - let testContract - beforeEach(async () => { - registry = await Registry.new(true) - - library1 = await LinkedLibrary1.new({ from: accounts[0] }) - library3 = await LinkedLibrary3.new({ from: accounts[0] }) - LinkedLibrary2.link('LinkedLibrary3', library3.address) - library2 = await LinkedLibrary2.new({ from: accounts[0] }) - - TestContract.link('LinkedLibrary1', library1.address) - TestContract.link('LinkedLibrary2', library2.address) - testContract = await deployProxiedContract(TestContract, accounts[0]) - - await registry.setAddressFor('TestContract', testContract.address) - }) - - describe('verifyBytecodes', () => { - it(`doesn't throw on matching contracts`, async () => { - await verifyBytecodes(['TestContract'], buildArtifacts, registry, [], Proxy, web3) - assert(true) - }) - - it(`throws when a contract's bytecodes don't match`, async () => { - const oldBytecode = artifact.deployedBytecode - artifact.deployedBytecode = '0x0' + oldBytecode.slice(3, artifact.deployedBytecode.length) - await assertThrowsAsync( - verifyBytecodes(['TestContract'], buildArtifacts, registry, [], Proxy, web3) - ) - artifact.deployedBytecode = oldBytecode - }) - - it(`throws when a library's bytecodes don't match`, async () => { - const libraryArtifact = buildArtifacts.getArtifactByName('LinkedLibrary1') - const oldBytecode = libraryArtifact.deployedBytecode - libraryArtifact.deployedBytecode = - oldBytecode.slice(0, 44) + '00' + oldBytecode.slice(46, oldBytecode.length) - await assertThrowsAsync( - verifyBytecodes(['TestContract'], buildArtifacts, registry, [], Proxy, web3) - ) - libraryArtifact.deployedBytecode = oldBytecode - }) - - describe(`when a proposal upgrades a library's implementation`, () => { - const LinkedLibrary3Upgraded = makeTruffleContract( - upgradedLibBuildArtifacts.getArtifactByName('LinkedLibrary3') - ) - beforeEach(async () => { - library3 = await LinkedLibrary3Upgraded.new({ from: accounts[0] }) - LinkedLibrary2.link('LinkedLibrary3', library3.address) - library2 = await LinkedLibrary2.new({ from: accounts[0] }) - TestContract.link('LinkedLibrary2', library2.address) - testContract = await TestContract.new({ from: accounts[0] }) - }) - - it(`doesn't throw on matching contracts`, async () => { - const proposal = [ - { - contract: 'TestContractProxy', - function: '_setImplementation', - args: [testContract.address], - value: '0', - }, - ] - - await verifyBytecodes( - ['TestContract'], - upgradedLibBuildArtifacts, - registry, - proposal, - Proxy, - web3 - ) - assert(true) - }) - - it(`throws on different contracts`, async () => { - const proposal = [ - { - contract: 'TestContractProxy', - function: '_setImplementation', - args: [testContract.address], - value: '0', - }, - ] - - await assertThrowsAsync( - verifyBytecodes(['TestContract'], buildArtifacts, registry, proposal, Proxy, web3) - ) - }) - - it(`throws when the proposed address is wrong`, async () => { - const proposal = [ - { - contract: 'TestContractProxy', - function: '_setImplementation', - args: [accounts[1]], - value: '0', - }, - ] - - await assertThrowsAsync( - verifyBytecodes(['TestContract'], buildArtifacts, registry, proposal, Proxy, web3) - ) - }) - }) - - describe(`when a proposal upgrades a contract's implementation`, () => { - const TestContractUpgraded = makeTruffleContract( - upgradedContractBuildArtifacts.getArtifactByName('TestContract') - ) - beforeEach(async () => { - TestContractUpgraded.link('LinkedLibrary1', library1.address) - TestContractUpgraded.link('LinkedLibrary2', library2.address) - testContract = await TestContractUpgraded.new({ from: accounts[0] }) - }) - - it(`doesn't throw on matching contracts`, async () => { - const proposal = [ - { - contract: 'TestContractProxy', - function: '_setImplementation', - args: [testContract.address], - value: '0', - }, - ] - - await verifyBytecodes( - ['TestContract'], - upgradedContractBuildArtifacts, - registry, - proposal, - Proxy, - web3 - ) - assert(true) - }) - - it(`throws on different contracts`, async () => { - const proposal = [ - { - contract: 'TestContractProxy', - function: '_setImplementation', - args: [testContract.address], - value: '0', - }, - ] - - await assertThrowsAsync( - verifyBytecodes(['TestContract'], buildArtifacts, registry, proposal, Proxy, web3) - ) - }) - - it(`throws when the proposed address is wrong`, async () => { - const proposal = [ - { - contract: 'TestContractProxy', - function: '_setImplementation', - args: [accounts[1]], - value: '0', - }, - ] - - await assertThrowsAsync( - verifyBytecodes(['TestContract'], buildArtifacts, registry, proposal, Proxy, web3) - ) - }) - - it(`throws when there is no proposal`, async () => { - const proposal = [] - - await assertThrowsAsync( - verifyBytecodes( - ['TestContract'], - upgradedContractBuildArtifacts, - registry, - proposal, - Proxy, - web3 - ) - ) - }) - }) - - describe(`when a proposal changes a contract's proxy`, () => { - const TestContractUpgraded = makeTruffleContract( - upgradedContractBuildArtifacts.getArtifactByName('TestContract') - ) - beforeEach(async () => { - TestContractUpgraded.link('LinkedLibrary1', library1.address) - TestContractUpgraded.link('LinkedLibrary2', library2.address) - testContract = await deployProxiedContract(TestContractUpgraded, accounts[0]) - await registry.setAddressFor('TestContract', testContract.address) - }) - - it(`doesn't throw on matching contracts`, async () => { - const proposal = [ - { - contract: 'Registry', - function: 'setAddressFor', - args: ['TestContract', testContract.address], - value: '0', - }, - ] - - await verifyBytecodes( - ['TestContract'], - upgradedContractBuildArtifacts, - registry, - proposal, - Proxy, - web3 - ) - assert(true) - }) - - it(`throws on different contracts`, async () => { - const proposal = [ - { - contract: 'Registry', - function: 'setAddressFor', - args: ['TestContract', testContract.address], - value: '0', - }, - ] - - await assertThrowsAsync( - verifyBytecodes(['TestContract'], buildArtifacts, registry, proposal, Proxy, web3) - ) - }) - - it(`throws when the proposed address is wrong`, async () => { - const proposal = [ - { - contract: 'Registry', - function: 'setAddressFor', - args: ['TestContract', accounts[0]], - value: '0', - }, - ] - - await assertThrowsAsync( - verifyBytecodes(['TestContract'], buildArtifacts, registry, proposal, Proxy, web3) - ) - }) - }) - - it('throws when a proposal does not only proxy or registry repointing', async () => { - const proposal = [ - { - contract: 'GoldToken', - function: 'transfer', - args: [NULL_ADDRESS, '100000000'], - value: '0', - }, - ] - - await assertThrowsAsync( - verifyBytecodes( - ['TestContract'], - upgradedContractBuildArtifacts, - registry, - proposal, - Proxy, - web3 - ) - ) - }) - }) - }) -}) diff --git a/packages/protocol/test/compatibility/version.ts b/packages/protocol/test/compatibility/version.ts deleted file mode 100644 index 4a1bcdb3a..000000000 --- a/packages/protocol/test/compatibility/version.ts +++ /dev/null @@ -1,247 +0,0 @@ -import { - ContractVersion, - ContractVersionChecker, - ContractVersionDelta, - DEFAULT_VERSION_STRING, - Delta, - DeltaUtil, -} from '@celo/protocol/lib/compatibility/version' -import { assert } from 'chai' - -describe('#version()', () => { - describe('ContractVersion', () => { - it('returns false on invalid string for isValid', () => { - assert.isFalse(ContractVersion.isValid('1.2.3')) - assert.isFalse(ContractVersion.isValid('1.2')) - assert.isFalse(ContractVersion.isValid('1.2.3.5.')) - assert.isFalse(ContractVersion.isValid('test')) - assert.isFalse(ContractVersion.isValid('1.a.3.4')) - assert.isFalse(ContractVersion.isValid('-1.0.9.787')) - }) - - it('returns true on valid string for isValid', () => { - assert.isTrue(ContractVersion.isValid('1.2.3.4')) - assert.isTrue(ContractVersion.isValid('10.0.224.9')) - }) - - describe('with a new ContractVersion instance', () => { - it('sets properties correctly', () => { - const version = new ContractVersion(1, 2, 3, 4) - assert.equal(version.storage, 1) - assert.equal(version.major, 2) - assert.equal(version.minor, 3) - assert.equal(version.patch, 4) - }) - - it('has a correct toString method', () => { - const version = new ContractVersion(2, 7, 9, 1) - assert.equal(version.toString(), '2.7.9.1') - }) - }) - - describe('ContractVersion.fromGetVersionNumberReturnValue', () => { - it('parses the buffer correctly', () => { - const zeros = '0'.repeat(63) - const buffer = Buffer.from(`${zeros}1${zeros}2${zeros}3${zeros}4`, 'hex') - const version = ContractVersion.fromGetVersionNumberReturnValue(buffer) - assert.equal(version.toString(), '1.2.3.4') - }) - - it('parses larger hex digits correctly', () => { - const zeros = '0'.repeat(63) - const buffer = Buffer.from(`${zeros}a${zeros}b${zeros}c${zeros}d`, 'hex') - const version = ContractVersion.fromGetVersionNumberReturnValue(buffer) - assert.equal(version.toString(), '10.11.12.13') - }) - - it('parses larger hex numbers correctly', () => { - const zeros = '0'.repeat(62) - const buffer = Buffer.from(`${zeros}10${zeros}11${zeros}fe${zeros}ff`, 'hex') - const version = ContractVersion.fromGetVersionNumberReturnValue(buffer) - assert.equal(version.toString(), '16.17.254.255') - }) - }) - }) - - describe('ContractVersionDelta', () => { - describe('ContractVersionDelta.fromChanges', () => { - it('properly sets the storage Delta', () => { - const cvd = ContractVersionDelta.fromChanges(true, false, true, true) - assert.equal(cvd.storage, Delta.Increment) - assert.equal(cvd.major, Delta.Reset) - assert.equal(cvd.minor, Delta.Reset) - assert.equal(cvd.patch, Delta.Reset) - }) - - it('properly sets the storage Delta', () => { - const cvd2 = ContractVersionDelta.fromChanges(false, false, true, true) - assert.equal(cvd2.storage, Delta.None) - assert.notEqual(cvd2.major, Delta.Reset) - }) - - it('properly sets the major Delta', () => { - const cvd = ContractVersionDelta.fromChanges(false, true, true, true) - assert.equal(cvd.major, Delta.Increment) - assert.equal(cvd.minor, Delta.Reset) - assert.equal(cvd.patch, Delta.Reset) - }) - - it('properly sets the major Delta', () => { - const cvd2 = ContractVersionDelta.fromChanges(false, false, true, true) - assert.equal(cvd2.major, Delta.None) - assert.notEqual(cvd2.minor, Delta.Reset) - }) - - it('properly sets the minor Delta', () => { - const cvd = ContractVersionDelta.fromChanges(false, false, true, true) - assert.equal(cvd.minor, Delta.Increment) - assert.equal(cvd.patch, Delta.Reset) - }) - - it('properly sets the minor Delta', () => { - const cvd2 = ContractVersionDelta.fromChanges(false, false, false, true) - assert.equal(cvd2.minor, Delta.None) - assert.notEqual(cvd2.patch, Delta.Reset) - }) - - it('properly sets the patch Delta', () => { - const cvd = ContractVersionDelta.fromChanges(false, false, false, true) - assert.equal(cvd.patch, Delta.Increment) - }) - - it('properly sets the patch Delta', () => { - const cvd2 = ContractVersionDelta.fromChanges(false, false, false, false) - assert.equal(cvd2.patch, Delta.None) - }) - }) - - describe('with a new ContractVersionDelta instance', () => { - it('sets properties correctly', () => { - const cvd = new ContractVersionDelta(Delta.None, Delta.Reset, Delta.Increment, Delta.None) - assert.equal(cvd.storage, Delta.None) - assert.equal(cvd.major, Delta.Reset) - assert.equal(cvd.minor, Delta.Increment) - assert.equal(cvd.patch, Delta.None) - - const cvd2 = new ContractVersionDelta(Delta.Reset, Delta.None, Delta.None, Delta.Increment) - assert.equal(cvd2.storage, Delta.Reset) - assert.equal(cvd2.major, Delta.None) - assert.equal(cvd2.minor, Delta.None) - assert.equal(cvd2.patch, Delta.Increment) - }) - - it('has a correct toString method', () => { - assert.equal( - new ContractVersionDelta(Delta.None, Delta.Reset, Delta.Increment, Delta.None).toString(), - '=.0.+1.=' - ) - assert.equal( - new ContractVersionDelta( - Delta.Reset, - Delta.Increment, - Delta.Increment, - Delta.Increment - ).toString(), - '0.+1.+1.+1' - ) - assert.equal( - new ContractVersionDelta( - Delta.Increment, - Delta.Reset, - Delta.Reset, - Delta.Reset - ).toString(), - '+1.0.0.0' - ) - assert.equal( - new ContractVersionDelta( - Delta.None, - Delta.Increment, - Delta.Increment, - Delta.None - ).toString(), - '=.+1.+1.=' - ) - }) - - it('has a correct applyTo method', () => { - const v1 = new ContractVersion(10, 20, 30, 40) - const v2 = new ContractVersionDelta( - Delta.None, - Delta.Reset, - Delta.Increment, - Delta.None - ).appliedTo(v1) - assert.equal(v2.storage, 10) - assert.equal(v2.major, 0) - assert.equal(v2.minor, 31) - assert.equal(v2.patch, 40) - - const v3 = new ContractVersionDelta( - Delta.Increment, - Delta.Reset, - Delta.Reset, - Delta.Reset - ).appliedTo(v1) - assert.equal(v3.storage, 11) - assert.equal(v3.major, 0) - assert.equal(v3.minor, 0) - assert.equal(v3.patch, 0) - }) - }) - }) - - describe('DeltaUtil', () => { - it('has a correct applyToNumber method', () => { - assert.equal(DeltaUtil.applyToNumber(Delta.Reset, 7), 0) - assert.equal(DeltaUtil.applyToNumber(Delta.Increment, 9), 10) - assert.equal(DeltaUtil.applyToNumber(Delta.None, 11), 11) - }) - }) - - describe('ContractVersionChecker', () => { - describe('when the expected version matches', () => { - const oldVersion = new ContractVersion(1, 2, 3, 4) - const newVersion = new ContractVersion(2, 0, 0, 0) - const cvd = ContractVersionDelta.fromChanges(true, false, true, false) - const cvc = new ContractVersionChecker(oldVersion, newVersion, cvd) - - it('returns the expected version number', () => { - assert.equal(cvc.expectedVersion().toString(), '2.0.0.0') - }) - - it('returns that the expected version number matches', () => { - assert.isTrue(cvc.matches()) - }) - }) - - describe('when the old version is null', () => { - const newVersion = new ContractVersion(1, 1, 0, 0) - const cvd = ContractVersionDelta.fromChanges(false, false, false, false) - const cvc = new ContractVersionChecker(null, newVersion, cvd) - - it('returns the default expected version number', () => { - assert.equal(cvc.expectedVersion().toString(), DEFAULT_VERSION_STRING) - }) - - it('returns that the expected version number matches', () => { - assert.isTrue(cvc.matches()) - }) - }) - - describe('when the expected version does not match', () => { - const oldVersion = new ContractVersion(1, 0, 1, 1) - const newVersion = new ContractVersion(1, 1, 0, 0) - const cvd = ContractVersionDelta.fromChanges(false, false, true, true) - const cvc = new ContractVersionChecker(oldVersion, newVersion, cvd) - - it('returns the expected version number', () => { - assert.equal(cvc.expectedVersion().toString(), '1.0.2.0') - }) - - it('returns that the expected version number does not match', () => { - assert.isFalse(cvc.matches()) - }) - }) - }) -}) diff --git a/packages/protocol/test/constants.ts b/packages/protocol/test/constants.ts deleted file mode 100644 index 6b1e89c70..000000000 --- a/packages/protocol/test/constants.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const SECONDS_IN_A_WEEK = 60 * 60 * 24 * 7 - -export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' diff --git a/packages/protocol/test/customHooks.ts b/packages/protocol/test/customHooks.ts deleted file mode 100644 index 1da6ba454..000000000 --- a/packages/protocol/test/customHooks.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { retryAsync } from '@celo/utils/lib/async' - -// Handles flakey `error: Invalid JSON RPC response: ""` error that seems to be caused by port exhaustion in CI. -// See https://github.com/ethereum/web3.js/issues/3425 and https://github.com/ethereum/web3.js/issues/926. -export const beforeEachWithRetries = ( - title: string, - numRetries: number, - sleepMs: number, - fn: () => any -) => - beforeEach(title, async () => { - await retryAsync(fn, numRetries, [], sleepMs) - }) diff --git a/packages/protocol/test/governance/network/blockchainparams.ts b/packages/protocol/test/governance/network/blockchainparams.ts deleted file mode 100644 index d660df828..000000000 --- a/packages/protocol/test/governance/network/blockchainparams.ts +++ /dev/null @@ -1,205 +0,0 @@ -import { - assertContainSubset, - assertEqualBN, - assertRevert, - assertTransactionRevertWithReason, - mineBlocks, -} from '@celo/protocol/lib/test-utils' -import { BigNumber } from 'bignumber.js' -import { BlockchainParametersInstance, BlockchainParametersTestContract } from 'types' - -const BlockchainParameters: BlockchainParametersTestContract = artifacts.require( - 'BlockchainParametersTest' -) - -// @ts-ignore -// TODO(mcortesi): Use BN -BlockchainParameters.numberFormat = 'BigNumber' - -// Hard coded in ganache. -const EPOCH = 100 - -contract('BlockchainParameters', (accounts: string[]) => { - let blockchainParameters: BlockchainParametersInstance - const gasLimit = 7000000 - const gasForNonGoldCurrencies = 50000 - - beforeEach(async () => { - blockchainParameters = await BlockchainParameters.new() - }) - - describe('#setBlockGasLimit()', () => { - it('should set the variable', async () => { - await blockchainParameters.setBlockGasLimit(gasLimit) - assert.equal((await blockchainParameters.blockGasLimit()).toNumber(), gasLimit) - }) - it('should emit the corresponding event', async () => { - const resp = await blockchainParameters.setBlockGasLimit(gasLimit) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'BlockGasLimitSet', - args: { - limit: new BigNumber(gasLimit), - }, - }) - }) - it('only owner should be able to set', async () => { - await assertTransactionRevertWithReason( - blockchainParameters.setBlockGasLimit(gasLimit, { - from: accounts[1], - }), - 'Ownable: caller is not the owner' - ) - }) - }) - - describe('#setIntrinsicGasForAlternativeFeeCurrency()', () => { - it('should set the variable', async () => { - await blockchainParameters.setIntrinsicGasForAlternativeFeeCurrency(gasForNonGoldCurrencies) - assertEqualBN( - gasForNonGoldCurrencies, - await blockchainParameters.intrinsicGasForAlternativeFeeCurrency() - ) - }) - it('should emit the corresponding event', async () => { - const resp = await blockchainParameters.setIntrinsicGasForAlternativeFeeCurrency( - gasForNonGoldCurrencies - ) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'IntrinsicGasForAlternativeFeeCurrencySet', - args: { - gas: new BigNumber(gasForNonGoldCurrencies), - }, - }) - }) - it('only owner should be able to set', async () => { - await assertTransactionRevertWithReason( - blockchainParameters.setIntrinsicGasForAlternativeFeeCurrency(gasLimit, { - from: accounts[1], - }), - 'Ownable: caller is not the owner' - ) - }) - }) - - describe('#getUptimeLookbackWindow()', () => { - it('should fail if not initalized', async () => - assertRevert(blockchainParameters.getUptimeLookbackWindow())) - - it('should fail if initialized, but still on current epoch', async () => { - await blockchainParameters.setUptimeLookbackWindow(20) - await assertRevert(blockchainParameters.getUptimeLookbackWindow()) - }) - }) - - describe('#setUptimeLookbackWindow()', () => { - const newValue = 20 - - it('should set the value for the next epoch', async () => { - await blockchainParameters.setUptimeLookbackWindow(newValue) - // wait an epoch to find new value - await mineBlocks(EPOCH, web3) - assert.equal((await blockchainParameters.getUptimeLookbackWindow()).toNumber(), newValue) - }) - - it('multiple calls within epoch only applies last', async () => { - // make 2 calls - await blockchainParameters.setUptimeLookbackWindow(newValue) - await blockchainParameters.setUptimeLookbackWindow(50) - - // after the epoch, find last value set - await mineBlocks(EPOCH, web3) - assert.equal((await blockchainParameters.getUptimeLookbackWindow()).toNumber(), 50) - }) - - it('should emit the corresponding event', async () => { - const resp = await blockchainParameters.setUptimeLookbackWindow(newValue) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'UptimeLookbackWindowSet', - args: { - window: new BigNumber(newValue), - }, - }) - }) - - it('only owner should be able to set', () => - assertTransactionRevertWithReason( - blockchainParameters.setUptimeLookbackWindow(newValue, { - from: accounts[1], - }), - 'Ownable: caller is not the owner' - )) - - it('should fail when using value lower than safe minimum', () => - assertTransactionRevertWithReason( - blockchainParameters.setUptimeLookbackWindow(2), - 'UptimeLookbackWindow must be within safe range' - )) - - it('should fail when using value greater than safe maximum', () => - assertTransactionRevertWithReason( - blockchainParameters.setUptimeLookbackWindow(721), - 'UptimeLookbackWindow must be within safe range' - )) - - it('should fail when using value greater than epochSize - 2', () => - assertTransactionRevertWithReason( - blockchainParameters.setUptimeLookbackWindow(EPOCH - 1), - 'UptimeLookbackWindow must be smaller or equal to epochSize - 2' - )) - }) - - describe('#initialize()', () => { - const lookbackWindow = 20 - - it('should set the variables', async () => { - await blockchainParameters.initialize(gasForNonGoldCurrencies, gasLimit, lookbackWindow) - assert.equal((await blockchainParameters.blockGasLimit()).toNumber(), gasLimit) - - // need to wait an epoch for uptimeLookbackWindow - await mineBlocks(EPOCH, web3) - assert.equal( - (await blockchainParameters.getUptimeLookbackWindow()).toNumber(), - lookbackWindow - ) - }) - it('should emit correct events', async () => { - const resp = await blockchainParameters.initialize( - gasForNonGoldCurrencies, - gasLimit, - lookbackWindow - ) - assert.equal(resp.logs.length, 4) - assertContainSubset(resp.logs[2], { - event: 'IntrinsicGasForAlternativeFeeCurrencySet', - args: { - gas: new BigNumber(gasForNonGoldCurrencies), - }, - }) - assertContainSubset(resp.logs[1], { - event: 'BlockGasLimitSet', - args: { - limit: new BigNumber(gasLimit), - }, - }) - assertContainSubset(resp.logs[0], { - event: 'OwnershipTransferred', - args: { - previousOwner: accounts[0], - newOwner: accounts[0], - }, - }) - assertContainSubset(resp.logs[3], { - event: 'UptimeLookbackWindowSet', - args: { - window: new BigNumber(lookbackWindow), - }, - }) - }) - }) -}) diff --git a/packages/protocol/test/governance/network/governance.ts b/packages/protocol/test/governance/network/governance.ts deleted file mode 100644 index 4617193a9..000000000 --- a/packages/protocol/test/governance/network/governance.ts +++ /dev/null @@ -1,4511 +0,0 @@ -import { NULL_ADDRESS, trimLeading0x } from '@celo/base/lib/address' -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { getParsedSignatureOfAddress } from '@celo/protocol/lib/signing-utils' -import { - assertBalance, - assertEqualBN, - assertLogMatches2, - assertRevert, - assertTransactionRevertWithReason, - createAndAssertDelegatorDelegateeSigners, - matchAny, - mineToNextEpoch, - stripHexEncoding, - timeTravel, -} from '@celo/protocol/lib/test-utils' -import { concurrentMap } from '@celo/utils/lib/async' -import { zip } from '@celo/utils/lib/collections' -import { fixed1, multiply, toFixed } from '@celo/utils/lib/fixidity' -import { bufferToHex, toBuffer } from '@ethereumjs/util' -import BigNumber from 'bignumber.js' -import { keccak256 } from 'ethereum-cryptography/keccak' -import { hexToBytes, utf8ToBytes } from 'ethereum-cryptography/utils' -import { - AccountsContract, - AccountsInstance, - GovernanceTestContract, - GovernanceTestInstance, - MockLockedGoldContract, - MockLockedGoldInstance, - MockValidatorsContract, - MockValidatorsInstance, - RegistryContract, - RegistryInstance, - TestTransactionsContract, - TestTransactionsInstance, -} from 'types' - -const Governance: GovernanceTestContract = artifacts.require('GovernanceTest') -const Accounts: AccountsContract = artifacts.require('Accounts') -const MockLockedGold: MockLockedGoldContract = artifacts.require('MockLockedGold') -const MockValidators: MockValidatorsContract = artifacts.require('MockValidators') -const Registry: RegistryContract = artifacts.require('Registry') -const TestTransactions: TestTransactionsContract = artifacts.require('TestTransactions') - -// @ts-ignore -// TODO(mcortesi): Use BN -Governance.numberFormat = 'BigNumber' - -const parseProposalParams = (proposalParams: any) => { - return { - proposer: proposalParams[0], - deposit: proposalParams[1], - timestamp: proposalParams[2].toNumber(), - transactionCount: proposalParams[3].toNumber(), - descriptionUrl: proposalParams[4], - networkWeight: proposalParams[5], - approved: proposalParams[6], - } -} - -const parseTransactionParams = (transactionParams: any) => { - return { - value: transactionParams[0].toNumber(), - destination: transactionParams[1], - data: transactionParams[2], - } -} - -enum VoteValue { - None = 0, - Abstain, - No, - Yes, -} - -enum Stage { - None = 0, - Queued, - Approval, - Referendum, - Execution, - Expiration, -} - -interface Transaction { - value: number - destination: string - data: Buffer -} - -// TODO(asa): Test dequeueProposalsIfReady -// TODO(asa): Dequeue explicitly to make the gas cost of operations more clear -contract('Governance', (accounts: string[]) => { - let governance: GovernanceTestInstance - let accountsInstance: AccountsInstance - let mockLockedGold: MockLockedGoldInstance - let mockValidators: MockValidatorsInstance - let testTransactions: TestTransactionsInstance - let registry: RegistryInstance - const nullFunctionId = '0x00000000' - const account = accounts[0] - const approver = accounts[0] - const otherAccount = accounts[1] - const nonOwner = accounts[1] - const nonApprover = accounts[1] - const concurrentProposals = 1 - const minDeposit = 5 - const queueExpiry = 60 * 60 // 1 hour - const dequeueFrequency = 10 * 60 // 10 minutes - const referendumStageDuration = 5 * 60 // 5 minutes - const executionStageDuration = 1 * 60 // 1 minute - const participationBaseline = toFixed(5 / 10) - const participationFloor = toFixed(5 / 100) - const baselineUpdateFactor = toFixed(1 / 5) - const baselineQuorumFactor = toFixed(1) - const yesVotes = 100 - const participation = toFixed(1) - const expectedParticipationBaseline = multiply(baselineUpdateFactor, participation).plus( - multiply(fixed1.minus(baselineUpdateFactor), participationBaseline) - ) - const descriptionUrl = 'https://descriptionUrl.sample.com' - let transactionSuccess1: Transaction - let transactionSuccess2: Transaction - let transactionFail: Transaction - let salt: string - let hotfixHash: Buffer - let hotfixHashStr: string - beforeEach(async () => { - accountsInstance = await Accounts.new(true) - governance = await Governance.new() - mockLockedGold = await MockLockedGold.new() - mockValidators = await MockValidators.new() - registry = await Registry.new(true) - testTransactions = await TestTransactions.new() - await governance.initialize( - registry.address, - approver, - concurrentProposals, - minDeposit, - queueExpiry, - dequeueFrequency, - referendumStageDuration, - executionStageDuration, - participationBaseline, - participationFloor, - baselineUpdateFactor, - baselineQuorumFactor - ) - await registry.setAddressFor(CeloContractName.Accounts, accountsInstance.address) - await registry.setAddressFor(CeloContractName.LockedGold, mockLockedGold.address) - await registry.setAddressFor(CeloContractName.Validators, mockValidators.address) - await accountsInstance.initialize(registry.address) - await accountsInstance.createAccount() - await mockLockedGold.setAccountTotalGovernancePower(account, yesVotes) - await mockLockedGold.setTotalLockedGold(yesVotes) - transactionSuccess1 = { - value: 0, - destination: testTransactions.address, - data: toBuffer( - // @ts-ignore - testTransactions.contract.methods.setValue(1, 1, true).encodeABI() - ), - } - transactionSuccess2 = { - value: 0, - destination: testTransactions.address, - data: toBuffer( - // @ts-ignore - testTransactions.contract.methods.setValue(2, 1, true).encodeABI() - ), - } - transactionFail = { - value: 0, - destination: testTransactions.address, - data: toBuffer( - // @ts-ignore - testTransactions.contract.methods.setValue(3, 1, false).encodeABI() - ), - } - salt = '0x657ed9d64e84fa3d1af43b3a307db22aba2d90a158015df1c588c02e24ca08f0' - const encodedParam = web3.eth.abi.encodeParameters( - ['uint256[]', 'address[]', 'bytes', 'uint256[]', 'bytes32'], - [ - [String(transactionSuccess1.value)], - [transactionSuccess1.destination.toString()], - transactionSuccess1.data, - [String(transactionSuccess1.data.length)], - salt, - ] - ) - - hotfixHash = toBuffer(keccak256(hexToBytes(trimLeading0x(encodedParam)))) - hotfixHashStr = bufferToHex(hotfixHash) - }) - - describe('#initialize()', () => { - it('should have set the owner', async () => { - const owner: string = await governance.owner() - assert.equal(owner, accounts[0]) - }) - - it('should have set concurrentProposals', async () => { - const actualConcurrentProposals = await governance.concurrentProposals() - assertEqualBN(actualConcurrentProposals, concurrentProposals) - }) - - it('should have set minDeposit', async () => { - const actualMinDeposit = await governance.minDeposit() - assertEqualBN(actualMinDeposit, minDeposit) - }) - - it('should have set queueExpiry', async () => { - const actualQueueExpiry = await governance.queueExpiry() - assertEqualBN(actualQueueExpiry, queueExpiry) - }) - - it('should have set dequeueFrequency', async () => { - const actualDequeueFrequency = await governance.dequeueFrequency() - assertEqualBN(actualDequeueFrequency, dequeueFrequency) - }) - - it('should have set stageDurations', async () => { - const actualReferendumStageDuration = await governance.getReferendumStageDuration() - const actualExecutionStageDuration = await governance.getExecutionStageDuration() - assertEqualBN(actualReferendumStageDuration, referendumStageDuration) - assertEqualBN(actualExecutionStageDuration, executionStageDuration) - }) - - it('should have set participationParameters', async () => { - const [ - actualParticipationBaseline, - actualParticipationFloor, - actualBaselineUpdateFactor, - actualBaselineQuorumFactor, - ] = await governance.getParticipationParameters() - assertEqualBN(actualParticipationBaseline, participationBaseline) - assertEqualBN(actualParticipationFloor, participationFloor) - assertEqualBN(actualBaselineUpdateFactor, baselineUpdateFactor) - assertEqualBN(actualBaselineQuorumFactor, baselineQuorumFactor) - }) - - // TODO(asa): Consider testing reversion when 0 values provided - it('should not be callable again', async () => { - await assertTransactionRevertWithReason( - governance.initialize( - registry.address, - approver, - concurrentProposals, - minDeposit, - queueExpiry, - dequeueFrequency, - referendumStageDuration, - executionStageDuration, - participationBaseline, - participationFloor, - baselineUpdateFactor, - baselineQuorumFactor - ), - 'contract already initialized' - ) - }) - }) - - describe('#setApprover', () => { - const newApprover = accounts[2] - it('should set the approver', async () => { - await governance.setApprover(newApprover) - assert.equal(await governance.approver(), newApprover) - }) - - it('should emit the ApproverSet event', async () => { - const resp = await governance.setApprover(newApprover) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ApproverSet', - args: { - approver: newApprover, - }, - }) - }) - - it('should revert when approver is the null address', async () => { - await assertTransactionRevertWithReason( - governance.setApprover(NULL_ADDRESS), - 'Approver cannot be 0' - ) - }) - - it('should revert when the approver is unchanged', async () => { - await assertTransactionRevertWithReason( - governance.setApprover(approver), - 'Approver unchanged' - ) - }) - - it('should revert when called by anyone other than the owner', async () => { - await assertTransactionRevertWithReason( - governance.setApprover(newApprover, { from: nonOwner }), - 'Ownable: caller is not the owner' - ) - }) - }) - - describe('#setMinDeposit', () => { - const newMinDeposit = 1 - it('should set the minimum deposit', async () => { - await governance.setMinDeposit(newMinDeposit) - assert.equal((await governance.minDeposit()).toNumber(), newMinDeposit) - }) - - it('should emit the MinDepositSet event', async () => { - const resp = await governance.setMinDeposit(newMinDeposit) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'MinDepositSet', - args: { - minDeposit: new BigNumber(newMinDeposit), - }, - }) - }) - - it('should revert when the minDeposit is unchanged', async () => { - await assertTransactionRevertWithReason( - governance.setMinDeposit(minDeposit), - 'Minimum deposit unchanged' - ) - }) - - it('should revert when called by anyone other than the owner', async () => { - await assertTransactionRevertWithReason( - governance.setMinDeposit(newMinDeposit, { from: nonOwner }), - 'Ownable: caller is not the owner' - ) - }) - }) - - describe('#setConcurrentProposals', () => { - const newConcurrentProposals = 2 - it('should set the concurrent proposals', async () => { - await governance.setConcurrentProposals(newConcurrentProposals) - assert.equal((await governance.concurrentProposals()).toNumber(), newConcurrentProposals) - }) - - it('should emit the ConcurrentProposalsSet event', async () => { - const resp = await governance.setConcurrentProposals(newConcurrentProposals) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ConcurrentProposalsSet', - args: { - concurrentProposals: new BigNumber(newConcurrentProposals), - }, - }) - }) - - it('should revert when concurrent proposals is 0', async () => { - await assertTransactionRevertWithReason( - governance.setConcurrentProposals(0), - 'Number of proposals must be larger than zero' - ) - }) - - it('should revert when concurrent proposals is unchanged', async () => { - await assertTransactionRevertWithReason( - governance.setConcurrentProposals(concurrentProposals), - 'Number of proposals unchanged' - ) - }) - - it('should revert when called by anyone other than the owner', async () => { - await assertTransactionRevertWithReason( - governance.setConcurrentProposals(newConcurrentProposals, { from: nonOwner }), - 'Ownable: caller is not the owner' - ) - }) - }) - - describe('#setQueueExpiry', () => { - const newQueueExpiry = 2 - it('should set the queue expiry', async () => { - await governance.setQueueExpiry(newQueueExpiry) - assert.equal((await governance.queueExpiry()).toNumber(), newQueueExpiry) - }) - - it('should emit the QueueExpirySet event', async () => { - const resp = await governance.setQueueExpiry(newQueueExpiry) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'QueueExpirySet', - args: { - queueExpiry: new BigNumber(newQueueExpiry), - }, - }) - }) - - it('should revert when queue expiry is 0', async () => { - await assertTransactionRevertWithReason( - governance.setQueueExpiry(0), - 'QueueExpiry must be larger than 0' - ) - }) - - it('should revert when queue expiry is unchanged', async () => { - await assertTransactionRevertWithReason( - governance.setQueueExpiry(queueExpiry), - 'QueueExpiry unchanged' - ) - }) - - it('should revert when called by anyone other than the owner', async () => { - await assertTransactionRevertWithReason( - governance.setQueueExpiry(newQueueExpiry, { from: nonOwner }), - 'Ownable: caller is not the owner' - ) - }) - }) - - describe('#setDequeueFrequency', () => { - const newDequeueFrequency = 2 - it('should set the dequeue frequency', async () => { - await governance.setDequeueFrequency(newDequeueFrequency) - assert.equal((await governance.dequeueFrequency()).toNumber(), newDequeueFrequency) - }) - - it('should emit the DequeueFrequencySet event', async () => { - const resp = await governance.setDequeueFrequency(newDequeueFrequency) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'DequeueFrequencySet', - args: { - dequeueFrequency: new BigNumber(newDequeueFrequency), - }, - }) - }) - - it('should revert when dequeue frequency is 0', async () => { - await assertTransactionRevertWithReason( - governance.setDequeueFrequency(0), - 'dequeueFrequency must be larger than 0' - ) - }) - - it('should revert when dequeue frequency is unchanged', async () => { - await assertTransactionRevertWithReason( - governance.setDequeueFrequency(dequeueFrequency), - 'dequeueFrequency unchanged' - ) - }) - - it('should revert when called by anyone other than the owner', async () => { - await assertTransactionRevertWithReason( - governance.setDequeueFrequency(newDequeueFrequency, { from: nonOwner }), - 'Ownable: caller is not the owner' - ) - }) - }) - - describe('#setReferendumStageDuration', () => { - const newReferendumStageDuration = 2 - it('should set the referendum stage duration', async () => { - await governance.setReferendumStageDuration(newReferendumStageDuration) - const actualReferendumStageDuration = await governance.getReferendumStageDuration() - assertEqualBN(actualReferendumStageDuration, newReferendumStageDuration) - }) - - it('should emit the ReferendumStageDurationSet event', async () => { - const resp = await governance.setReferendumStageDuration(newReferendumStageDuration) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ReferendumStageDurationSet', - args: { - referendumStageDuration: new BigNumber(newReferendumStageDuration), - }, - }) - }) - - it('should revert when referendum stage duration is 0', async () => { - await assertTransactionRevertWithReason( - governance.setReferendumStageDuration(0), - 'Duration must be larger than 0' - ) - }) - - it('should revert when referendum stage duration is unchanged', async () => { - await assertTransactionRevertWithReason( - governance.setReferendumStageDuration(referendumStageDuration), - 'Duration unchanged' - ) - }) - - it('should revert when called by anyone other than the owner', async () => { - await assertTransactionRevertWithReason( - governance.setReferendumStageDuration(newReferendumStageDuration, { from: nonOwner }), - 'Ownable: caller is not the owner' - ) - }) - }) - - describe('#setExecutionStageDuration', () => { - const newExecutionStageDuration = 2 - it('should set the execution stage duration', async () => { - await governance.setExecutionStageDuration(newExecutionStageDuration) - const actualExecutionStageDuration = await governance.getExecutionStageDuration() - assertEqualBN(actualExecutionStageDuration, newExecutionStageDuration) - }) - - it('should emit the ExecutionStageDurationSet event', async () => { - const resp = await governance.setExecutionStageDuration(newExecutionStageDuration) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ExecutionStageDurationSet', - args: { - executionStageDuration: new BigNumber(newExecutionStageDuration), - }, - }) - }) - - it('should revert when execution stage duration is 0', async () => { - await assertTransactionRevertWithReason( - governance.setExecutionStageDuration(0), - 'Duration must be larger than 0' - ) - }) - - it('should revert when execution stage duration is unchanged', async () => { - await assertTransactionRevertWithReason( - governance.setExecutionStageDuration(executionStageDuration), - 'Duration unchanged' - ) - }) - - it('should revert when called by anyone other than the owner', async () => { - await assertTransactionRevertWithReason( - governance.setExecutionStageDuration(newExecutionStageDuration, { from: nonOwner }), - 'Ownable: caller is not the owner' - ) - }) - }) - - describe('#setParticipationFloor', () => { - const differentParticipationFloor = toFixed(2 / 100) - - it('should set the participation floor', async () => { - await governance.setParticipationFloor(differentParticipationFloor) - const [, actualParticipationFloor, ,] = await governance.getParticipationParameters() - assertEqualBN(actualParticipationFloor, differentParticipationFloor) - }) - - it('should emit the ParticipationFloorSet event', async () => { - const resp = await governance.setParticipationFloor(differentParticipationFloor) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ParticipationFloorSet', - args: { - participationFloor: differentParticipationFloor, - }, - }) - }) - - it('should revert if new participation floor is above 1', async () => { - await assertTransactionRevertWithReason( - governance.setParticipationFloor(toFixed(101 / 100)), - 'Participation floor greater than one' - ) - }) - - it('should revert when called by anyone other than the owner', async () => { - await assertTransactionRevertWithReason( - governance.setParticipationFloor(differentParticipationFloor, { from: nonOwner }), - 'Ownable: caller is not the owner' - ) - }) - }) - - describe('#setBaselineUpdateFactor', () => { - const differentBaselineUpdateFactor = toFixed(2 / 5) - - it('should set the participation update coefficient', async () => { - await governance.setBaselineUpdateFactor(differentBaselineUpdateFactor) - const [, , actualBaselineUpdateFactor] = await governance.getParticipationParameters() - assertEqualBN(actualBaselineUpdateFactor, differentBaselineUpdateFactor) - }) - - it('should emit the ParticipationBaselineUpdateFactorSet event', async () => { - const resp = await governance.setBaselineUpdateFactor(differentBaselineUpdateFactor) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ParticipationBaselineUpdateFactorSet', - args: { - baselineUpdateFactor: differentBaselineUpdateFactor, - }, - }) - }) - - it('should revert if new update coefficient is above 1', async () => { - await assertTransactionRevertWithReason( - governance.setBaselineUpdateFactor(toFixed(101 / 100)), - 'Baseline update factor greater than one' - ) - }) - - it('should revert when called by anyone other than the owner', async () => { - await assertTransactionRevertWithReason( - governance.setBaselineUpdateFactor(differentBaselineUpdateFactor, { from: nonOwner }), - 'Ownable: caller is not the owner' - ) - }) - }) - - describe('#setBaselineQuorumFactor', () => { - const differentBaselineQuorumFactor = toFixed(8 / 10) - - it('should set the critical baseline level', async () => { - await governance.setBaselineQuorumFactor(differentBaselineQuorumFactor) - const [, , , actualBaselineQuorumFactor] = await governance.getParticipationParameters() - assertEqualBN(actualBaselineQuorumFactor, differentBaselineQuorumFactor) - }) - - it('should emit the ParticipationBaselineQuorumFactorSet event', async () => { - const resp = await governance.setBaselineQuorumFactor(differentBaselineQuorumFactor) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ParticipationBaselineQuorumFactorSet', - args: { - baselineQuorumFactor: differentBaselineQuorumFactor, - }, - }) - }) - - it('should revert if new critical baseline level is above 1', async () => { - await assertTransactionRevertWithReason( - governance.setBaselineQuorumFactor(toFixed(101 / 100)), - 'Baseline quorum factor greater than one' - ) - }) - - it('should revert when called by anyone other than the owner', async () => { - await assertTransactionRevertWithReason( - governance.setBaselineQuorumFactor(differentBaselineQuorumFactor, { from: nonOwner }), - 'Ownable: caller is not the owner' - ) - }) - }) - - // TODO(asa): Verify that when we set the constitution for a function ID then the proper constitution is applied to a proposal. - describe('#setConstitution', () => { - const threshold = toFixed(2 / 3) - let functionId - let differentFunctionId - let destination - - beforeEach(() => { - destination = governance.address - }) - - describe('when the function id is 0', () => { - beforeEach(() => { - functionId = nullFunctionId - differentFunctionId = '0x12345678' - }) - - it('should set the default threshold', async () => { - await governance.setConstitution(destination, functionId, threshold) - const differentThreshold = await governance.getConstitution( - destination, - differentFunctionId - ) - assert.isTrue(differentThreshold.eq(threshold)) - }) - - it('should emit the ConstitutionSet event', async () => { - const resp = await governance.setConstitution(destination, functionId, threshold) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ConstitutionSet', - args: { - destination, - functionId: web3.utils.padRight(functionId, 64), - threshold, - }, - }) - }) - }) - - describe('when the function id is not 0', () => { - beforeEach(() => { - functionId = '0x87654321' - differentFunctionId = '0x12345678' - }) - - it('should set the function threshold', async () => { - await governance.setConstitution(destination, functionId, threshold) - const actualThreshold = await governance.getConstitution(destination, functionId) - assert.isTrue(actualThreshold.eq(threshold)) - }) - - it('should not set the default threshold', async () => { - await governance.setConstitution(destination, functionId, threshold) - const actualThreshold = await governance.getConstitution(destination, differentFunctionId) - assert.isTrue(actualThreshold.eq(toFixed(1 / 2))) - }) - - it('should emit the ConstitutionSet event', async () => { - const resp = await governance.setConstitution(destination, functionId, threshold) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ConstitutionSet', - args: { - destination, - functionId: web3.utils.padRight(functionId, 64), - threshold, - }, - }) - }) - }) - - it('should revert when the destination is the null address', async () => { - await assertTransactionRevertWithReason( - governance.setConstitution(NULL_ADDRESS, nullFunctionId, threshold), - 'Destination cannot be zero' - ) - }) - - it('should revert when the threshold is zero', async () => { - await assertTransactionRevertWithReason( - governance.setConstitution(destination, nullFunctionId, 0), - 'Threshold has to be greater than majority and not greater than unanimity' - ) - }) - - it('should revert when the threshold is not greater than a majority', async () => { - await assertTransactionRevertWithReason( - governance.setConstitution(destination, nullFunctionId, toFixed(1 / 2)), - 'Threshold has to be greater than majority and not greater than unanimity' - ) - }) - - it('should revert when the threshold is greater than 100%', async () => { - await assertTransactionRevertWithReason( - governance.setConstitution(destination, nullFunctionId, toFixed(101 / 100)), - 'Threshold has to be greater than majority and not greater than unanimity' - ) - }) - - it('should revert when called by anyone other than the owner', async () => { - await assertTransactionRevertWithReason( - governance.setConstitution(destination, nullFunctionId, threshold, { - from: nonOwner, - }), - 'Ownable: caller is not the owner' - ) - }) - }) - - describe('#propose()', () => { - const proposalId = 1 - - it('should return the proposal id', async () => { - const id = await governance.propose.call( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - assertEqualBN(id, proposalId) - }) - - it('should increment the proposal count', async () => { - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - assertEqualBN(await governance.proposalCount(), proposalId) - }) - - it('should add the proposal to the queue', async () => { - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - assert.isTrue(await governance.isQueued(proposalId)) - const [proposalIds, upvotes] = await governance.getQueue() - assertEqualBN(proposalIds[0], proposalId) - assertEqualBN(upvotes[0], 0) - }) - - describe('when making a proposal with zero transactions', () => { - it('should register the proposal', async () => { - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - await governance.propose([], [], [], [], descriptionUrl, { value: minDeposit }) - const timestamp = (await web3.eth.getBlock('latest')).timestamp - const proposal = parseProposalParams(await governance.getProposal(proposalId)) - assert.equal(proposal.proposer, accounts[0]) - assert.equal(proposal.deposit, minDeposit) - assert.equal(proposal.timestamp, timestamp) - assert.equal(proposal.transactionCount, 0) - assert.equal(proposal.descriptionUrl, descriptionUrl) - assertEqualBN(proposal.networkWeight, 0) - assert.equal(proposal.approved, false) - }) - - it('should emit the ProposalQueued event', async () => { - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - const resp = await governance.propose([], [], [], [], descriptionUrl, { value: minDeposit }) - const timestamp = (await web3.eth.getBlock('latest')).timestamp - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ProposalQueued', - args: { - proposalId: new BigNumber(1), - proposer: accounts[0], - deposit: new BigNumber(minDeposit), - timestamp, - transactionCount: 0, - }, - }) - }) - }) - - describe('when making a proposal with one transaction', () => { - it('should register the proposal', async () => { - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - const timestamp = (await web3.eth.getBlock('latest')).timestamp - const proposal = parseProposalParams(await governance.getProposal(proposalId)) - assert.equal(proposal.proposer, accounts[0]) - assert.equal(proposal.deposit, minDeposit) - assert.equal(proposal.timestamp, timestamp) - assert.equal(proposal.transactionCount, 1) - assert.equal(proposal.descriptionUrl, descriptionUrl) - assertEqualBN(proposal.networkWeight, 0) - assert.equal(proposal.approved, false) - }) - - it('should register the proposal transactions', async () => { - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - const transaction = parseTransactionParams( - await governance.getProposalTransaction(proposalId, 0) - ) - assert.equal(transaction.value, transactionSuccess1.value) - assert.equal(transaction.destination, transactionSuccess1.destination) - assert.isTrue( - Buffer.from(stripHexEncoding(transaction.data), 'hex').equals(transactionSuccess1.data) - ) - }) - - it('should emit the ProposalQueued event', async () => { - const resp = await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - const timestamp = (await web3.eth.getBlock('latest')).timestamp - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ProposalQueued', - args: { - proposalId: new BigNumber(1), - proposer: accounts[0], - deposit: new BigNumber(minDeposit), - timestamp, - transactionCount: 1, - }, - }) - }) - - it('should revert if one tries to make a proposal without description', async () => { - await assertRevert( - governance.propose.call( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - '', - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - ) - }) - }) - - describe('when making a proposal with two transactions', () => { - it('should register the proposal', async () => { - await governance.propose( - [transactionSuccess1.value, transactionSuccess2.value], - [transactionSuccess1.destination, transactionSuccess2.destination], - // @ts-ignore - Buffer.concat([transactionSuccess1.data, transactionSuccess2.data]), - [transactionSuccess1.data.length, transactionSuccess2.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - const timestamp = (await web3.eth.getBlock('latest')).timestamp - const proposal = parseProposalParams(await governance.getProposal(proposalId)) - assert.equal(proposal.proposer, accounts[0]) - assert.equal(proposal.deposit, minDeposit) - assert.equal(proposal.timestamp, timestamp) - assert.equal(proposal.transactionCount, 2) - assert.equal(proposal.descriptionUrl, descriptionUrl) - assertEqualBN(proposal.networkWeight, 0) - assert.equal(proposal.approved, false) - }) - - it('should register the proposal transactions', async () => { - await governance.propose( - [transactionSuccess1.value, transactionSuccess2.value], - [transactionSuccess1.destination, transactionSuccess2.destination], - // @ts-ignore - Buffer.concat([transactionSuccess1.data, transactionSuccess2.data]), - [transactionSuccess1.data.length, transactionSuccess2.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - const transaction1 = parseTransactionParams( - await governance.getProposalTransaction(proposalId, 0) - ) - assert.equal(transaction1.value, transactionSuccess1.value) - assert.equal(transaction1.destination, transactionSuccess1.destination) - assert.isTrue( - Buffer.from(stripHexEncoding(transaction1.data), 'hex').equals(transactionSuccess1.data) - ) - const transaction2 = parseTransactionParams( - await governance.getProposalTransaction(proposalId, 1) - ) - assert.equal(transaction2.value, transactionSuccess2.value) - assert.equal(transaction2.destination, transactionSuccess2.destination) - assert.isTrue( - Buffer.from(stripHexEncoding(transaction2.data), 'hex').equals(transactionSuccess2.data) - ) - }) - - it('should emit the ProposalQueued event', async () => { - const resp = await governance.propose( - [transactionSuccess1.value, transactionSuccess2.value], - [transactionSuccess1.destination, transactionSuccess2.destination], - // @ts-ignore - Buffer.concat([transactionSuccess1.data, transactionSuccess2.data]), - [transactionSuccess1.data.length, transactionSuccess2.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - const timestamp = (await web3.eth.getBlock('latest')).timestamp - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ProposalQueued', - args: { - proposalId: new BigNumber(1), - proposer: accounts[0], - deposit: new BigNumber(minDeposit), - timestamp, - transactionCount: 2, - }, - }) - }) - }) - - describe('when it has been more than dequeueFrequency since the last dequeue', () => { - let originalLastDequeue: BigNumber - beforeEach(async () => { - originalLastDequeue = await governance.lastDequeue() - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - }) - - it('should dequeue queued proposal(s)', async () => { - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - assert.isFalse(await governance.isQueued(proposalId)) - assert.equal((await governance.getQueueLength()).toNumber(), 1) - assert.equal((await governance.dequeued(0)).toNumber(), proposalId) - assert.isBelow(originalLastDequeue.toNumber(), (await governance.lastDequeue()).toNumber()) - }) - }) - - it('should not update lastDequeue when no queued proposal(s)', async () => { - const originalLastDequeue = await governance.lastDequeue() - await timeTravel(dequeueFrequency, web3) - - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - - assert.equal((await governance.getQueueLength()).toNumber(), 1) - assert.equal((await governance.lastDequeue()).toNumber(), originalLastDequeue.toNumber()) - }) - }) - - describe('#upvote()', () => { - const proposalId = new BigNumber(1) - beforeEach(async () => { - await mockLockedGold.setAccountTotalLockedGold(account, yesVotes) - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - }) - - it('should increase the number of upvotes for the proposal', async () => { - await governance.upvote(proposalId, 0, 0) - assertEqualBN(await governance.getUpvotes(proposalId), yesVotes) - }) - - it('should mark the account as having upvoted the proposal', async () => { - await governance.upvote(proposalId, 0, 0) - const [recordId, recordWeight] = await governance.getUpvoteRecord(account) - assertEqualBN(recordId, proposalId) - assertEqualBN(recordWeight, yesVotes) - }) - - it('should return true', async () => { - const success = await governance.upvote.call(proposalId, 0, 0) - assert.isTrue(success) - }) - - it('should emit the ProposalUpvoted event', async () => { - const resp = await governance.upvote(proposalId, 0, 0) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ProposalUpvoted', - args: { - proposalId: new BigNumber(proposalId), - account, - upvotes: new BigNumber(yesVotes), - }, - }) - }) - - it('should revert when upvoting a proposal that is not queued', async () => { - await assertTransactionRevertWithReason( - governance.upvote(proposalId.plus(1), 0, 0), - 'cannot upvote a proposal not in the queue' - ) - }) - - describe('when the upvoted proposal is at the end of the queue', () => { - const upvotedProposalId = 2 - beforeEach(async () => { - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - }) - - it('should sort the upvoted proposal to the front of the queue', async () => { - await governance.upvote(upvotedProposalId, proposalId, 0) - const [proposalIds, upvotes] = await governance.getQueue() - assert.equal(proposalIds[0].toNumber(), upvotedProposalId) - assertEqualBN(upvotes[0], yesVotes) - }) - }) - - describe('when the upvoted proposal is expired', () => { - const otherProposalId = 2 - beforeEach(async () => { - // Prevent dequeues for the sake of this test. - await governance.setDequeueFrequency(queueExpiry * 2) - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - const otherAccount1 = accounts[1] - await accountsInstance.createAccount({ from: otherAccount1 }) - await mockLockedGold.setAccountTotalLockedGold(otherAccount1, yesVotes) - await governance.upvote(otherProposalId, proposalId, 0, { from: otherAccount1 }) - await timeTravel(queueExpiry, web3) - }) - - it('should return false', async () => { - const success = await governance.upvote.call(proposalId, otherProposalId, 0) - assert.isFalse(success) - }) - - it('should remove the proposal from the queue', async () => { - await governance.upvote(proposalId, 0, 0) - assert.isFalse(await governance.isQueued(proposalId)) - const [proposalIds] = await governance.getQueue() - assert.notInclude( - proposalIds.map((x) => x.toNumber()), - proposalId.toNumber() - ) - }) - - it('should emit the ProposalExpired event', async () => { - const resp = await governance.upvote(proposalId, 0, 0) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ProposalExpired', - args: { - proposalId: new BigNumber(proposalId), - }, - }) - }) - }) - - describe('when it has been more than dequeueFrequency since the last dequeue', () => { - const upvotedProposalId = 2 - let originalLastDequeue: BigNumber - beforeEach(async () => { - originalLastDequeue = await governance.lastDequeue() - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - }) - - it('should dequeue queued proposal(s)', async () => { - const queueLength = await governance.getQueueLength() - await governance.upvote(upvotedProposalId, 0, 0) - assert.isFalse(await governance.isQueued(proposalId)) - assert.equal( - (await governance.getQueueLength()).toNumber(), - queueLength.minus(concurrentProposals).toNumber() - ) - assertEqualBN(await governance.dequeued(0), proposalId) - assert.isBelow(originalLastDequeue.toNumber(), (await governance.lastDequeue()).toNumber()) - }) - - it('should revert when upvoting a proposal that will be dequeued', async () => { - await assertTransactionRevertWithReason( - governance.upvote(proposalId, 0, 0), - 'cannot upvote a proposal not in the queue' - ) - }) - }) - - describe('when the previously upvoted proposal is in the queue and expired', () => { - const upvotedProposalId = 2 - // Expire the upvoted proposal without dequeueing it. - const queueExpiry1 = 60 - beforeEach(async () => { - await governance.setQueueExpiry(60) - await governance.upvote(proposalId, 0, 0) - await timeTravel(queueExpiry1, web3) - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - }) - - it('should increase the number of upvotes for the proposal', async () => { - await governance.upvote(upvotedProposalId, 0, 0) - assertEqualBN(await governance.getUpvotes(upvotedProposalId), yesVotes) - }) - - it('should mark the account as having upvoted the proposal', async () => { - await governance.upvote(upvotedProposalId, 0, 0) - const [recordId, recordWeight] = await governance.getUpvoteRecord(account) - assertEqualBN(recordId, upvotedProposalId) - assertEqualBN(recordWeight, yesVotes) - }) - - it('should return true', async () => { - const success = await governance.upvote.call(upvotedProposalId, 0, 0) - assert.isTrue(success) - }) - - it('should emit the ProposalExpired event', async () => { - const resp = await governance.upvote(upvotedProposalId, 0, 0) - assert.equal(resp.logs.length, 2) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ProposalExpired', - args: { - proposalId: new BigNumber(proposalId), - }, - }) - }) - it('should emit the ProposalUpvoted event', async () => { - const resp = await governance.upvote(upvotedProposalId, 0, 0) - assert.equal(resp.logs.length, 2) - const log = resp.logs[1] - assertLogMatches2(log, { - event: 'ProposalUpvoted', - args: { - proposalId: new BigNumber(upvotedProposalId), - account, - upvotes: new BigNumber(yesVotes), - }, - }) - }) - }) - }) - - describe('#revokeUpvote()', () => { - const proposalId = new BigNumber(1) - beforeEach(async () => { - await mockLockedGold.setAccountTotalLockedGold(account, yesVotes) - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await governance.upvote(proposalId, 0, 0) - }) - - it('should return true', async () => { - const success = await governance.revokeUpvote.call(0, 0) - assert.isTrue(success) - }) - - it('should decrease the number of upvotes for the proposal', async () => { - await governance.revokeUpvote(0, 0) - assertEqualBN(await governance.getUpvotes(proposalId), 0) - }) - - it('should mark the account as not having upvoted a proposal', async () => { - await governance.revokeUpvote(0, 0) - const [recordId, recordWeight] = await governance.getUpvoteRecord(account) - assertEqualBN(recordId, 0) - assertEqualBN(recordWeight, 0) - }) - - it('should emit the ProposalUpvoteRevoked event', async () => { - const resp = await governance.revokeUpvote(0, 0) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ProposalUpvoteRevoked', - args: { - proposalId: new BigNumber(proposalId), - account, - revokedUpvotes: new BigNumber(yesVotes), - }, - }) - }) - - it('should revert when the account does not have an upvoted proposal', async () => { - await governance.revokeUpvote(0, 0) - await assertTransactionRevertWithReason( - governance.revokeUpvote(0, 0), - 'Account has no historical upvote' - ) - }) - - describe('when the upvoted proposal has expired', () => { - beforeEach(async () => { - await timeTravel(queueExpiry, web3) - }) - - it('should remove the proposal from the queue', async () => { - await governance.revokeUpvote(0, 0) - assert.isFalse(await governance.isQueued(proposalId)) - const [proposalIds, upvotes] = await governance.getQueue() - assert.equal(proposalIds.length, 0) - assert.equal(upvotes.length, 0) - }) - - it('should mark the account as not having upvoted a proposal', async () => { - await governance.revokeUpvote(0, 0) - const [recordId, recordWeight] = await governance.getUpvoteRecord(account) - assertEqualBN(recordId, 0) - assertEqualBN(recordWeight, 0) - }) - - it('should emit the ProposalExpired event', async () => { - const resp = await governance.revokeUpvote(0, 0) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ProposalExpired', - args: { - proposalId: new BigNumber(proposalId), - }, - }) - }) - }) - - describe('when it has been more than dequeueFrequency since the last dequeue', () => { - let originalLastDequeue: BigNumber - beforeEach(async () => { - originalLastDequeue = await governance.lastDequeue() - await timeTravel(dequeueFrequency, web3) - }) - - it('should dequeue the proposal', async () => { - await governance.revokeUpvote(0, 0) - assert.isFalse(await governance.isQueued(proposalId)) - assert.equal((await governance.getQueueLength()).toNumber(), 0) - assertEqualBN(await governance.dequeued(0), proposalId) - assert.isBelow(originalLastDequeue.toNumber(), (await governance.lastDequeue()).toNumber()) - }) - - it('should mark the account as not having upvoted a proposal', async () => { - await governance.revokeUpvote(0, 0) - const [recordId, recordWeight] = await governance.getUpvoteRecord(account) - assertEqualBN(recordId, 0) - assertEqualBN(recordWeight, 0) - }) - }) - }) - - describe('#withdraw()', () => { - const proposalId = 1 - const index = 0 - beforeEach(async () => { - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - await governance.approve(proposalId, index) - }) - - describe('when the caller was the proposer of a dequeued proposal', () => { - it('should return true', async () => { - // @ts-ignore - const success = await governance.withdraw.call() - assert.isTrue(success) - }) - - it('should withdraw the refunded deposit when the proposal was dequeued', async () => { - const startBalance = new BigNumber(await web3.eth.getBalance(account)) - await governance.withdraw() - await assertBalance(account, startBalance.plus(minDeposit)) - }) - }) - - it('should revert when the caller was not the proposer of a dequeued proposal', async () => { - await assertTransactionRevertWithReason( - governance.withdraw({ from: accounts[1] }), - 'Nothing to withdraw' - ) - }) - }) - - describe('#approve()', () => { - const proposalId = 1 - const index = 0 - beforeEach(async () => { - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - }) - - it('should return true', async () => { - const success = await governance.approve.call(proposalId, index) - assert.isTrue(success) - }) - - it('should return updated proposal details correctly', async () => { - await governance.approve(proposalId, index) - const proposal = parseProposalParams(await governance.getProposal(proposalId)) - assert.equal(proposal.proposer, accounts[0]) - assert.equal(proposal.deposit, minDeposit) - assert.equal(proposal.transactionCount, 1) - assert.equal(proposal.descriptionUrl, descriptionUrl) - assert.equal(proposal.approved, true) - assertEqualBN(proposal.networkWeight, yesVotes) - }) - - it('should set the proposal to approved', async () => { - await governance.approve(proposalId, index) - assert.isTrue(await governance.isApproved(proposalId)) - }) - - it('should emit the ProposalDequeued event', async () => { - const resp = await governance.approve(proposalId, index) - assert.equal(resp.logs.length, 2) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ProposalDequeued', - args: { - proposalId: new BigNumber(proposalId), - timestamp: matchAny, - }, - }) - }) - - it('should emit the ProposalApproved event', async () => { - const resp = await governance.approve(proposalId, index) - assert.equal(resp.logs.length, 2) - const log = resp.logs[1] - assertLogMatches2(log, { - event: 'ProposalApproved', - args: { - proposalId: new BigNumber(proposalId), - }, - }) - }) - - it('should revert when the index is out of bounds', async () => { - await assertTransactionRevertWithReason( - governance.approve(proposalId, index + 1), - 'Provided index greater than dequeue length.' - ) - }) - - it('should revert if the proposal id does not match the index', async () => { - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - const otherProposalId = 2 - await assertTransactionRevertWithReason( - governance.approve(otherProposalId, index), - 'Proposal not dequeued' - ) - }) - - it('should revert when not called by the approver', async () => { - await assertTransactionRevertWithReason( - governance.approve(proposalId, index, { from: nonApprover }), - 'msg.sender not approver' - ) - }) - - it('should revert when the proposal is queued', async () => { - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await assertTransactionRevertWithReason( - governance.approve(proposalId + 1, index), - 'Proposal not dequeued' - ) - }) - - it('should revert if the proposal has already been approved', async () => { - await governance.approve(proposalId, index) - await assertTransactionRevertWithReason( - governance.approve(proposalId, index), - 'Proposal already approved' - ) - }) - - describe('when the proposal is within referendum stage', () => { - beforeEach(async () => { - // Dequeue the other proposal. - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - }) - - it('should return true', async () => { - const success = await governance.approve.call(proposalId, index) - assert.isTrue(success) - }) - - it('should not delete the proposal', async () => { - await governance.approve(proposalId, index) - assert.isTrue(await governance.proposalExists(proposalId)) - }) - - it('should not remove the proposal ID from dequeued', async () => { - await governance.approve(proposalId, index) - const dequeued = await governance.getDequeue() - assert.include( - dequeued.map((x) => x.toNumber()), - proposalId - ) - }) - - it('should emit the ParticipationBaselineUpdated event', async () => { - const resp = await governance.approve(proposalId, index) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ProposalApproved', - args: { - proposalId: new BigNumber(proposalId), - }, - }) - }) - }) - - describe('when the proposal is past the referendum stage', () => { - beforeEach(async () => { - // Dequeue the other proposal. - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(referendumStageDuration + 1, web3) - }) - - it('should return false', async () => { - const success = await governance.approve.call(proposalId, index) - assert.isFalse(success) - }) - - it('should delete the proposal', async () => { - await governance.approve(proposalId, index) - assert.isFalse(await governance.proposalExists(proposalId)) - }) - - it('should remove the proposal ID from dequeued', async () => { - await governance.approve(proposalId, index) - const dequeued = await governance.getDequeue() - assert.notInclude( - dequeued.map((x) => x.toNumber()), - proposalId - ) - }) - - it('should add the index to empty indices', async () => { - await governance.approve(proposalId, index) - const emptyIndex = await governance.emptyIndices(0) - assert.equal(emptyIndex.toNumber(), index) - }) - - it('should not emit the ParticipationBaselineUpdated event', async () => { - const resp = await governance.approve(proposalId, index) - assert.equal(resp.logs.length, 0) - }) - }) - }) - - describe('#revokeVotes()', () => { - beforeEach(async () => { - await governance.setConcurrentProposals(3) - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await governance.propose( - [transactionSuccess2.value], - [transactionSuccess2.destination], - // @ts-ignore bytes type - transactionSuccess2.data, - [transactionSuccess2.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - await governance.approve(1, 0) - await governance.approve(2, 1) - await governance.approve(3, 2) - await mockLockedGold.setAccountTotalGovernancePower(account, yesVotes) - }) - - for (let numVoted = 0; numVoted < 3; numVoted++) { - describe(`when account has voted on ${numVoted} proposals`, () => { - const value = VoteValue.Yes - beforeEach(async () => { - for (let i = 0; i < numVoted; i++) { - await governance.vote(i + 1, i, value) - } - }) - - it('should unset the most recent referendum proposal voted on', async () => { - await governance.revokeVotes() - const mostRecentReferendum = await governance.getMostRecentReferendumProposal(account) - assert.equal(mostRecentReferendum.toNumber(), 0) - }) - - it('should return false on `isVoting`', async () => { - await governance.revokeVotes() - const voting = await governance.isVoting(accounts[0]) - assert.isFalse(voting) - }) - - it(`should emit the ProposalVoteRevokedV2 event ${numVoted} times`, async () => { - const resp = await governance.revokeVotes() - assert.equal(resp.logs.length, numVoted) - resp.logs.map((log, i) => - assertLogMatches2(log, { - event: 'ProposalVoteRevokedV2', - args: { - proposalId: i + 1, - account, - yesVotes, - noVotes: 0, - abstainVotes: 0, - }, - }) - ) - }) - - it('should not revert when proposals are not in the Referendum stage', async () => { - await timeTravel(referendumStageDuration, web3) - const success = await governance.revokeVotes.call() - assert.isTrue(success) - }) - }) - } - - for (let numVoted = 0; numVoted < 3; numVoted++) { - describe(`when account has partially voted on ${numVoted} proposals`, () => { - const yes = 10 - const no = 30 - const abstain = 0 - beforeEach(async () => { - for (let i = 0; i < numVoted; i++) { - await governance.votePartially(i + 1, i, yes, no, abstain) - } - }) - - it('should unset the most recent referendum proposal voted on', async () => { - await governance.revokeVotes() - const mostRecentReferendum = await governance.getMostRecentReferendumProposal(account) - assert.equal(mostRecentReferendum.toNumber(), 0) - }) - - it('should return false on `isVoting`', async () => { - await governance.revokeVotes() - const voting = await governance.isVoting(accounts[0]) - const totalVotesByAccount = await governance.getAmountOfGoldUsedForVoting(accounts[0]) - assert.isFalse(voting) - assert.isTrue(totalVotesByAccount.eq(0)) - }) - - it(`should emit the ProposalVoteRevokedV2 event ${numVoted} times`, async () => { - const resp = await governance.revokeVotes() - assert.equal(resp.logs.length, numVoted) - resp.logs.map((log, i) => - assertLogMatches2(log, { - event: 'ProposalVoteRevokedV2', - args: { - proposalId: i + 1, - account, - yesVotes: yes, - noVotes: no, - abstainVotes: abstain, - }, - }) - ) - }) - - it('should not revert when proposals are not in the Referendum stage', async () => { - await timeTravel(referendumStageDuration, web3) - const success = await governance.revokeVotes.call() - assert.isTrue(success) - }) - }) - } - }) - - describe('#vote()', () => { - const proposalId = 1 - const index = 0 - const value = VoteValue.Yes - - describe('when proposal is approved', () => { - beforeEach(async () => { - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - await governance.approve(proposalId, index) - await mockLockedGold.setAccountTotalGovernancePower(account, yesVotes) - }) - - it('should return true', async () => { - const success = await governance.vote.call(proposalId, index, value, { - gas: 7000000, - from: account, - }) - assert.isTrue(success) - }) - - it('should increment the vote totals', async () => { - await governance.vote(proposalId, index, value) - const [yes, ,] = await governance.getVoteTotals(proposalId) - assert.equal(yes.toNumber(), yesVotes) - }) - - it("should set the voter's vote record", async () => { - await governance.vote(proposalId, index, value) - const [recordProposalId, , , yesVotesRecord, noVotesRecord, abstainVotesRecord] = - await governance.getVoteRecord(account, index) - assertEqualBN(recordProposalId, proposalId) - assertEqualBN(yesVotesRecord, yesVotes) - assertEqualBN(noVotesRecord, 0) - assertEqualBN(abstainVotesRecord, 0) - }) - - it('should set the most recent referendum proposal voted on', async () => { - await governance.vote(proposalId, index, value) - assert.equal( - (await governance.getMostRecentReferendumProposal(account)).toNumber(), - proposalId - ) - }) - - it('should emit the ProposalVotedV2 event', async () => { - const resp = await governance.vote(proposalId, index, value) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ProposalVotedV2', - args: { - proposalId: new BigNumber(proposalId), - account, - yesVotes, - noVotes: 0, - abstainVotes: 0, - }, - }) - }) - - it('should revert when the account weight is 0', async () => { - await mockLockedGold.setAccountTotalGovernancePower(account, 0) - await assertTransactionRevertWithReason( - governance.vote(proposalId, index, value), - 'Voter weight zero' - ) - }) - - it('should revert when the index is out of bounds', async () => { - await assertTransactionRevertWithReason( - governance.vote(proposalId, index + 1, value), - 'Provided index greater than dequeue length.' - ) - }) - - it('should revert if the proposal id does not match the index', async () => { - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - const otherProposalId = 2 - await assertTransactionRevertWithReason( - governance.vote(otherProposalId, index, value), - 'Proposal not dequeued' - ) - }) - - describe('when voting on two proposals', () => { - const proposalId1 = 2 - const proposalId2 = 3 - const index1 = 1 - const index2 = 2 - beforeEach(async () => { - const newDequeueFrequency = 60 - await governance.setDequeueFrequency(newDequeueFrequency) - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(newDequeueFrequency, web3) - await governance.approve(proposalId1, index1) - await governance.propose( - [transactionSuccess2.value], - [transactionSuccess2.destination], - // @ts-ignore bytes type - transactionSuccess2.data, - [transactionSuccess2.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(newDequeueFrequency, web3) - await governance.approve(proposalId2, index2) - await mockLockedGold.setAccountTotalGovernancePower(account, yesVotes) - }) - - it('should set mostRecentReferendumProposal to the youngest proposal voted on', async () => { - await governance.vote(proposalId2, index2, value) - await governance.vote(proposalId1, index1, value) - const mostRecent = await governance.getMostRecentReferendumProposal(accounts[0]) - assert.equal(mostRecent.toNumber(), proposalId2) - }) - - it('should return true on `isVoting`', async () => { - await governance.vote(proposalId2, index2, value) - await governance.vote(proposalId1, index1, value) - const voting = await governance.isVoting(accounts[0]) - assert.isTrue(voting) - }) - - describe('after the first proposal expires', () => { - beforeEach(async () => { - await governance.vote(proposalId2, index2, value) - await governance.vote(proposalId1, index1, value) - await timeTravel(referendumStageDuration - 10, web3) - }) - - it('should still return true on `isVoting`', async () => { - const voting = await governance.isVoting(accounts[0]) - assert.isTrue(voting) - }) - - it('should no longer return true on `isVoting` after both expire', async () => { - await timeTravel(11, web3) - const voting = await governance.isVoting(accounts[0]) - assert.isFalse(voting) - }) - }) - }) - - describe('when the account has already voted on this proposal', () => { - const revoteTests = (oldValue, newValue) => { - it('should decrement the vote total from the previous vote', async () => { - await governance.vote(proposalId, index, newValue) - const voteTotals = await governance.getVoteTotals(proposalId) - assert.equal(voteTotals[3 - oldValue].toNumber(), 0) - }) - - it('should increment the vote total for the new vote', async () => { - await governance.vote(proposalId, index, newValue) - const voteTotals = await governance.getVoteTotals(proposalId) - assert.equal(voteTotals[3 - newValue].toNumber(), yesVotes) - }) - - it("should set the voter's vote record", async () => { - await governance.vote(proposalId, index, newValue) - const [recordProposalId, , , yesVotesRecord, noVotesRecord, abstainVotesRecord] = - await governance.getVoteRecord(account, index) - assert.equal(recordProposalId.toNumber(), proposalId) - - const votesNormalized = [0, abstainVotesRecord, noVotesRecord, yesVotesRecord] - - assertEqualBN(votesNormalized[newValue], yesVotes) - }) - } - - describe('when the account has already voted yes on this proposal', () => { - beforeEach(async () => { - await governance.vote(proposalId, index, VoteValue.Yes) - }) - - revoteTests(VoteValue.Yes, VoteValue.No) - }) - - describe('when the account has already voted no on this proposal', () => { - beforeEach(async () => { - await governance.vote(proposalId, index, VoteValue.No) - }) - - revoteTests(VoteValue.No, VoteValue.Abstain) - }) - - describe('when the account has already voted abstain on this proposal', () => { - beforeEach(async () => { - await governance.vote(proposalId, index, VoteValue.Abstain) - }) - - revoteTests(VoteValue.Abstain, VoteValue.Yes) - }) - }) - - describe('when the proposal is past the referendum stage and passing', () => { - beforeEach(async () => { - await governance.vote(proposalId, index, VoteValue.Yes) - await timeTravel(referendumStageDuration, web3) - }) - - it('should revert', async () => { - await assertRevert(governance.vote.call(proposalId, index, value)) - }) - }) - - describe('when the proposal is past the referendum stage and failing', () => { - beforeEach(async () => { - await governance.vote(proposalId, index, VoteValue.No) - await timeTravel(referendumStageDuration, web3) - }) - - it('should return false', async () => { - const success = await governance.vote.call(proposalId, index, value) - assert.isFalse(success) - }) - - it('should delete the proposal', async () => { - await governance.vote(proposalId, index, value) - assert.isFalse(await governance.proposalExists(proposalId)) - }) - - it('should remove the proposal ID from dequeued', async () => { - await governance.vote(proposalId, index, value) - const dequeued = await governance.getDequeue() - assert.notInclude( - dequeued.map((x) => x.toNumber()), - proposalId - ) - }) - - it('should add the index to empty indices', async () => { - await governance.vote(proposalId, index, value) - const emptyIndex = await governance.emptyIndices(0) - assert.equal(emptyIndex.toNumber(), index) - }) - - it('should update the participation baseline', async () => { - await governance.vote(proposalId, index, value) - const [actualParticipationBaseline, , ,] = await governance.getParticipationParameters() - assertEqualBN(actualParticipationBaseline, expectedParticipationBaseline) - }) - - it('should emit the ParticipationBaselineUpdated event', async () => { - const resp = await governance.vote(proposalId, index, value) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ParticipationBaselineUpdated', - args: { - participationBaseline: expectedParticipationBaseline, - }, - }) - }) - }) - }) - - describe('When proposal is approved and have signer', () => { - let accountSigner - beforeEach(async () => { - ;[accountSigner] = await createAndAssertDelegatorDelegateeSigners( - accountsInstance, - accounts, - account - ) - - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - await governance.approve(proposalId, index) - await mockLockedGold.setAccountTotalGovernancePower(account, yesVotes) - }) - - it('should return true', async () => { - const success = await governance.vote.call(proposalId, index, value, { - from: accountSigner, - }) - assert.isTrue(success) - }) - - it('should increment the vote totals', async () => { - await governance.vote(proposalId, index, value, { from: accountSigner }) - const [yes, ,] = await governance.getVoteTotals(proposalId) - assert.equal(yes.toNumber(), yesVotes) - }) - - it("should set the voter's vote record", async () => { - await governance.vote(proposalId, index, value, { from: accountSigner }) - const [recordProposalId, , , yesVotesRecord, noVotesRecord, abstainVotesRecord] = - await governance.getVoteRecord(account, index) - assertEqualBN(recordProposalId, proposalId) - assertEqualBN(yesVotesRecord, yesVotes) - assertEqualBN(noVotesRecord, 0) - assertEqualBN(abstainVotesRecord, 0) - }) - - it('should set the most recent referendum proposal voted on', async () => { - await governance.vote(proposalId, index, value, { from: accountSigner }) - assert.equal( - (await governance.getMostRecentReferendumProposal(account)).toNumber(), - proposalId - ) - }) - - it('should emit the ProposalVotedV2 event', async () => { - await governance.dequeueProposalsIfReady() - const resp = await governance.vote(proposalId, index, value, { from: accountSigner }) - assert.equal(resp.logs.length, resp.logs.length) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ProposalVotedV2', - args: { - proposalId: new BigNumber(proposalId), - account, - yesVotes, - noVotes: 0, - abstainVotes: 0, - }, - }) - }) - - it('should revert when the account weight is 0', async () => { - await mockLockedGold.setAccountTotalGovernancePower(account, 0) - await assertTransactionRevertWithReason( - governance.vote(proposalId, index, value, { from: accountSigner }), - 'Voter weight zero' - ) - }) - }) - - describe('when proposal is not approved', () => { - beforeEach(async () => { - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - await mockLockedGold.setAccountTotalGovernancePower(account, yesVotes) - }) - - it('should return true', async () => { - const success = await governance.vote.call(proposalId, index, value) - assert.isTrue(success) - }) - - it('should increment the vote totals', async () => { - await governance.vote(proposalId, index, value) - const [yes, ,] = await governance.getVoteTotals(proposalId) - assert.equal(yes.toNumber(), yesVotes) - }) - - it("should set the voter's vote record", async () => { - await governance.vote(proposalId, index, value) - const [recordProposalId, , , yesVotesRecord, noVotesRecord, abstainVotesRecord] = - await governance.getVoteRecord(account, index) - assertEqualBN(recordProposalId, proposalId) - assertEqualBN(yesVotesRecord, yesVotes) - assertEqualBN(noVotesRecord, 0) - assertEqualBN(abstainVotesRecord, 0) - }) - - it('should set the most recent referendum proposal voted on', async () => { - await governance.vote(proposalId, index, value) - assert.equal( - (await governance.getMostRecentReferendumProposal(account)).toNumber(), - proposalId - ) - }) - - it('should emit the ProposalVotedV2 event', async () => { - await governance.dequeueProposalsIfReady() - const resp = await governance.vote(proposalId, index, value) - assert.equal(resp.logs.length, resp.logs.length) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ProposalVotedV2', - args: { - proposalId: new BigNumber(proposalId), - account, - yesVotes, - noVotes: 0, - abstainVotes: 0, - }, - }) - }) - - it('should revert when the account weight is 0', async () => { - await mockLockedGold.setAccountTotalGovernancePower(account, 0) - await assertTransactionRevertWithReason( - governance.vote(proposalId, index, value), - 'Voter weight zero' - ) - }) - - it('should revert when the index is out of bounds', async () => { - await assertTransactionRevertWithReason( - governance.vote(proposalId, index + 1, value), - 'Provided index greater than dequeue length.' - ) - }) - - it('should revert if the proposal id does not match the index', async () => { - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - const otherProposalId = 2 - await assertTransactionRevertWithReason( - governance.vote(otherProposalId, index, value), - 'Proposal not dequeued' - ) - }) - }) - - describe('When voting on different proposal with same index', () => { - const proposalId2 = 2 - const otherAccountWeight = 100 - beforeEach(async () => { - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - await governance.approve(proposalId, index) - await mockLockedGold.setAccountTotalGovernancePower(account, yesVotes) - await governance.vote(proposalId, index, value) - await timeTravel(referendumStageDuration, web3) - await timeTravel(executionStageDuration, web3) - }) - - it('should ignore votes from previous proposal', async () => { - const dequeuedProposal1Dequeued = await governance.dequeued(index) - assertEqualBN(dequeuedProposal1Dequeued, proposalId) - - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await governance.execute(proposalId, index) - assert.isFalse(await governance.proposalExists(proposalId)) - - await timeTravel(dequeueFrequency + 1, web3) - await governance.dequeueProposalsIfReady() - await governance.approve.call(proposalId2, index) - assert.isTrue(await governance.proposalExists(proposalId2)) - - const dequeuedProposal2 = await governance.dequeued(index) - assertEqualBN(dequeuedProposal2, proposalId2) - await governance.getVoteTotals(proposalId2) - - const otherAccount1 = accounts[1] - await accountsInstance.createAccount({ from: otherAccount1 }) - await mockLockedGold.setAccountTotalGovernancePower(otherAccount1, otherAccountWeight) - await governance.vote(proposalId2, index, value, { from: otherAccount1 }) - - await governance.vote(proposalId2, index, VoteValue.No) - - const [yesVotesTotal, noVotesTotal, abstainVotesTotal] = await governance.getVoteTotals( - proposalId2 - ) - - assertEqualBN(yesVotesTotal, otherAccountWeight) - assertEqualBN(noVotesTotal, yesVotes) - assertEqualBN(abstainVotesTotal, 0) - }) - }) - }) - - describe('#votePartially()', () => { - const proposalId = 1 - const index = 0 - - describe('when proposal is approved', () => { - beforeEach(async () => { - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - await governance.approve(proposalId, index) - await mockLockedGold.setAccountTotalGovernancePower(account, yesVotes) - }) - - it('should return true', async () => { - const success = await governance.votePartially.call(proposalId, index, yesVotes, 0, 0, { - gas: 7000000, - from: account, - }) - assert.isTrue(success) - }) - - it('should increment the vote totals', async () => { - await governance.votePartially(proposalId, index, yesVotes, 0, 0) - const [yes, ,] = await governance.getVoteTotals(proposalId) - assert.equal(yes.toNumber(), yesVotes) - }) - - it('should increment the vote totals when voting partially', async () => { - const yes = 10 - const no = 50 - const abstain = 30 - await governance.votePartially(proposalId, index, yes, no, abstain) - const [yesTotal, noTotal, abstainTotal] = await governance.getVoteTotals(proposalId) - assert.equal(yesTotal.toNumber(), yes) - assert.equal(noTotal.toNumber(), no) - assert.equal(abstainTotal.toNumber(), abstain) - }) - - it("should set the voter's vote record", async () => { - await governance.votePartially(proposalId, index, yesVotes, 0, 0) - const [recordProposalId, , , yesVotesRecord] = await governance.getVoteRecord( - account, - index - ) - assertEqualBN(recordProposalId, proposalId) - assertEqualBN(yesVotesRecord, yesVotes) - }) - - it('should set the most recent referendum proposal voted on', async () => { - await governance.votePartially(proposalId, index, yesVotes, 0, 0) - assert.equal( - (await governance.getMostRecentReferendumProposal(account)).toNumber(), - proposalId - ) - }) - - it('should emit the ProposalVotedV2 event', async () => { - const resp = await governance.votePartially(proposalId, index, yesVotes, 0, 0) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ProposalVotedV2', - args: { - proposalId: new BigNumber(proposalId), - account, - yesVotes, - noVotes: 0, - abstainVotes: 0, - }, - }) - }) - - it('should revert when the account weight is 0', async () => { - await mockLockedGold.setAccountTotalGovernancePower(account, 0) - await assertTransactionRevertWithReason( - governance.votePartially(proposalId, index, yesVotes, 0, 0), - "Voter doesn't have enough locked Celo [(]formerly known as Celo Gold[)]" - ) - }) - - it('should revert when the account does not have enough gold', async () => { - await assertTransactionRevertWithReason( - governance.votePartially(proposalId, index, yesVotes + 1, 0, 0), - "Voter doesn't have enough locked Celo [(]formerly known as Celo Gold[)]" - ) - }) - - it('should revert when the account does not have enough gold when voting partially', async () => { - const noVotes = yesVotes - await assertTransactionRevertWithReason( - governance.votePartially(proposalId, index, yesVotes, noVotes, 0), - "Voter doesn't have enough locked Celo [(]formerly known as Celo Gold[)]" - ) - }) - - it('should revert when the index is out of bounds', async () => { - await assertTransactionRevertWithReason( - governance.votePartially(proposalId, index + 1, yesVotes, 0, 0), - 'Provided index greater than dequeue length.' - ) - }) - - it('should revert if the proposal id does not match the index', async () => { - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - const otherProposalId = 2 - await assertTransactionRevertWithReason( - governance.votePartially(otherProposalId, index, yesVotes, 0, 0), - 'Proposal not dequeued' - ) - }) - - describe('when voting on two proposals', () => { - const proposalId1 = 2 - const proposalId2 = 3 - const index1 = 1 - const index2 = 2 - beforeEach(async () => { - const newDequeueFrequency = 60 - await governance.setDequeueFrequency(newDequeueFrequency) - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(newDequeueFrequency, web3) - await governance.approve(proposalId1, index1) - await governance.propose( - [transactionSuccess2.value], - [transactionSuccess2.destination], - // @ts-ignore bytes type - transactionSuccess2.data, - [transactionSuccess2.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(newDequeueFrequency, web3) - await governance.approve(proposalId2, index2) - await mockLockedGold.setAccountTotalGovernancePower(account, yesVotes) - }) - - it('should set mostRecentReferendumProposal to the youngest proposal voted on', async () => { - await governance.votePartially(proposalId1, index1, yesVotes, 0, 0) - await governance.votePartially(proposalId2, index2, yesVotes, 0, 0) - const mostRecent = await governance.getMostRecentReferendumProposal(accounts[0]) - assert.equal(mostRecent.toNumber(), proposalId2) - }) - - it('should return true on `isVoting`', async () => { - await governance.votePartially(proposalId2, index2, yesVotes, 0, 0) - await governance.votePartially(proposalId1, index1, yesVotes, 0, 0) - const voting = await governance.isVoting(accounts[0]) - assert.isTrue(voting) - }) - - describe('after the first proposal expires', () => { - beforeEach(async () => { - await governance.votePartially(proposalId2, index2, yesVotes, 0, 0) - await governance.votePartially(proposalId1, index1, yesVotes, 0, 0) - await timeTravel(referendumStageDuration - 10, web3) - }) - - it('should still return true on `isVoting`', async () => { - const voting = await governance.isVoting(accounts[0]) - assert.isTrue(voting) - }) - - it('should no longer return true on `isVoting` after both expire', async () => { - await timeTravel(11, web3) - const voting = await governance.isVoting(accounts[0]) - assert.isFalse(voting) - }) - }) - }) - - describe('when the account has already voted partially on this proposal', () => { - const revoteTests = (newYes: number, newNo: number, newAbstain) => { - it('should set vote total correctly', async () => { - await governance.votePartially(proposalId, index, newYes, newNo, newAbstain) - const voteTotals = await governance.getVoteTotals(proposalId) - - assertEqualBN(voteTotals[0], newYes) - assertEqualBN(voteTotals[1], newNo) - assertEqualBN(voteTotals[2], newAbstain) - }) - - it("should set the voter's vote record", async () => { - await governance.votePartially(proposalId, index, newYes, newNo, newAbstain) - const [recordProposalId, , , yesVotesRecord, noVotesRecord, abstainVotesRecord] = - await governance.getVoteRecord(account, index) - assert.equal(recordProposalId.toNumber(), proposalId) - - assertEqualBN(yesVotesRecord, newYes) - assertEqualBN(noVotesRecord, newNo) - assertEqualBN(abstainVotesRecord, newAbstain) - }) - } - - describe('when the account has already voted yes and no on this proposal', () => { - const oldYes = 70 - const oldNo = 30 - const oldAbstain = 0 - - beforeEach(async () => { - await governance.votePartially(proposalId, index, oldYes, oldNo, oldAbstain) - }) - - revoteTests(30, 70, 0) - }) - - describe('when the account has already voted abstain and yes on this proposal', () => { - const oldYes = 0 - const oldNo = 70 - const oldAbstain = 30 - - beforeEach(async () => { - await governance.votePartially(proposalId, index, oldYes, oldNo, oldAbstain) - }) - - revoteTests(30, 0, 20) - }) - }) - - describe('when the account has already voted on this proposal', () => { - const voteWeight = yesVotes - const revoteTests = (newYes, newNo, newAbstain) => { - it('should decrement the vote total from the previous vote', async () => { - await governance.votePartially(proposalId, index, newYes, newNo, newAbstain) - const voteTotals = await governance.getVoteTotals(proposalId) - assertEqualBN(voteTotals[0], newYes) - assertEqualBN(voteTotals[1], newNo) - assertEqualBN(voteTotals[2], newAbstain) - }) - - it('should increment the vote total for the new vote', async () => { - await governance.votePartially(proposalId, index, newYes, newNo, newAbstain) - const voteTotals = await governance.getVoteTotals(proposalId) - assertEqualBN(voteTotals[0], newYes) - assertEqualBN(voteTotals[1], newNo) - assertEqualBN(voteTotals[2], newAbstain) - }) - - it("should set the voter's vote record", async () => { - await governance.votePartially(proposalId, index, newYes, newNo, newAbstain) - const [recordProposalId, , , yesVotesRecord, noVotesRecord, abstainVotesRecord] = - await governance.getVoteRecord(account, index) - assert.equal(recordProposalId.toNumber(), proposalId) - assertEqualBN(yesVotesRecord, newYes) - assertEqualBN(noVotesRecord, newNo) - assertEqualBN(abstainVotesRecord, newAbstain) - }) - } - - describe('when the account has already voted yes on this proposal', () => { - beforeEach(async () => { - await governance.votePartially(proposalId, index, yesVotes, 0, 0) - }) - - revoteTests(0, voteWeight, 0) - }) - - describe('when the account has already voted no on this proposal', () => { - beforeEach(async () => { - await governance.votePartially(proposalId, index, voteWeight, 0, 0) - }) - - revoteTests(0, 0, voteWeight) - }) - - describe('when the account has already voted abstain on this proposal', () => { - beforeEach(async () => { - await governance.votePartially(proposalId, index, 0, 0, voteWeight) - }) - - revoteTests(voteWeight, 0, 0) - }) - }) - - describe('when the proposal is past the referendum stage and passing', () => { - beforeEach(async () => { - await governance.votePartially(proposalId, index, yesVotes, 0, 0) - await timeTravel(referendumStageDuration, web3) - }) - - it('should revert', async () => { - await assertRevert(governance.votePartially.call(proposalId, index, yesVotes, 0, 0)) - }) - }) - - describe('when the proposal is past the referendum stage and failing', () => { - beforeEach(async () => { - await governance.votePartially(proposalId, index, 0, yesVotes, 0) - await timeTravel(referendumStageDuration, web3) - }) - - it('should return false', async () => { - const success = await governance.votePartially.call(proposalId, index, yesVotes, 0, 0) - assert.isFalse(success) - }) - - it('should delete the proposal', async () => { - await governance.votePartially(proposalId, index, yesVotes, 0, 0) - assert.isFalse(await governance.proposalExists(proposalId)) - }) - - it('should remove the proposal ID from dequeued', async () => { - await governance.votePartially(proposalId, index, yesVotes, 0, 0) - const dequeued = await governance.getDequeue() - assert.notInclude( - dequeued.map((x) => x.toNumber()), - proposalId - ) - }) - - it('should add the index to empty indices', async () => { - await governance.votePartially(proposalId, index, yesVotes, 0, 0) - const emptyIndex = await governance.emptyIndices(0) - assert.equal(emptyIndex.toNumber(), index) - }) - - it('should update the participation baseline', async () => { - await governance.votePartially(proposalId, index, yesVotes, 0, 0) - const [actualParticipationBaseline, , ,] = await governance.getParticipationParameters() - assertEqualBN(actualParticipationBaseline, expectedParticipationBaseline) - }) - - it('should emit the ParticipationBaselineUpdated event', async () => { - const resp = await governance.votePartially(proposalId, index, yesVotes, 0, 0) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ParticipationBaselineUpdated', - args: { - participationBaseline: expectedParticipationBaseline, - }, - }) - }) - }) - }) - - describe('when proposal is approved with signer', () => { - let accountSigner - - beforeEach(async () => { - ;[accountSigner] = await createAndAssertDelegatorDelegateeSigners( - accountsInstance, - accounts, - account - ) - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - await governance.approve(proposalId, index) - await mockLockedGold.setAccountTotalGovernancePower(account, yesVotes) - }) - - it('should return true', async () => { - const success = await governance.votePartially.call(proposalId, index, yesVotes, 0, 0, { - gas: 7000000, - from: accountSigner, - }) - assert.isTrue(success) - }) - - it('should increment the vote totals', async () => { - await governance.votePartially(proposalId, index, yesVotes, 0, 0, { from: accountSigner }) - const [yes, ,] = await governance.getVoteTotals(proposalId) - assert.equal(yes.toNumber(), yesVotes) - }) - - it('should increment the vote totals when voting partially', async () => { - const yes = 10 - const no = 50 - const abstain = 30 - await governance.votePartially(proposalId, index, yes, no, abstain, { from: accountSigner }) - const [yesTotal, noTotal, abstainTotal] = await governance.getVoteTotals(proposalId) - assert.equal(yesTotal.toNumber(), yes) - assert.equal(noTotal.toNumber(), no) - assert.equal(abstainTotal.toNumber(), abstain) - }) - - it("should set the voter's vote record", async () => { - await governance.votePartially(proposalId, index, yesVotes, 0, 0, { from: accountSigner }) - const [recordProposalId, , , yesVotesRecord] = await governance.getVoteRecord( - account, - index - ) - assertEqualBN(recordProposalId, proposalId) - assertEqualBN(yesVotesRecord, yesVotes) - }) - - it('should set the most recent referendum proposal voted on', async () => { - await governance.votePartially(proposalId, index, yesVotes, 0, 0, { from: accountSigner }) - assert.equal( - (await governance.getMostRecentReferendumProposal(account)).toNumber(), - proposalId - ) - }) - - it('should emit the ProposalVotedV2 event', async () => { - const resp = await governance.votePartially(proposalId, index, yesVotes, 0, 0, { - from: accountSigner, - }) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ProposalVotedV2', - args: { - proposalId: new BigNumber(proposalId), - account, - yesVotes, - noVotes: 0, - abstainVotes: 0, - }, - }) - }) - - it('should revert when the account weight is 0', async () => { - await mockLockedGold.setAccountTotalGovernancePower(account, 0) - await assertTransactionRevertWithReason( - governance.votePartially(proposalId, index, yesVotes, 0, 0, { from: accountSigner }), - "Voter doesn't have enough locked Celo [(]formerly known as Celo Gold[)]" - ) - }) - - it('should revert when the account does not have enough gold', async () => { - await assertTransactionRevertWithReason( - governance.votePartially(proposalId, index, yesVotes + 1, 0, 0, { from: accountSigner }), - "Voter doesn't have enough locked Celo [(]formerly known as Celo Gold[)]" - ) - }) - - it('should revert when the account does not have enough gold when voting partially', async () => { - const noVotes = yesVotes - await assertTransactionRevertWithReason( - governance.votePartially(proposalId, index, yesVotes, noVotes, 0, { - from: accountSigner, - }), - "Voter doesn't have enough locked Celo [(]formerly known as Celo Gold[)]" - ) - }) - - it('should revert when the index is out of bounds', async () => { - await assertTransactionRevertWithReason( - governance.votePartially(proposalId, index + 1, yesVotes, 0, 0, { from: accountSigner }), - 'Provided index greater than dequeue length.' - ) - }) - - it('should revert if the proposal id does not match the index', async () => { - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - const otherProposalId = 2 - await assertTransactionRevertWithReason( - governance.votePartially(otherProposalId, index, yesVotes, 0, 0, { from: accountSigner }), - 'Reason given: Proposal not dequeued.' - ) - }) - }) - - describe('when proposal is not approved', () => { - beforeEach(async () => { - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - await mockLockedGold.setAccountTotalGovernancePower(account, yesVotes) - }) - - it('should return true', async () => { - const success = await governance.votePartially.call(proposalId, index, yesVotes, 0, 0) - assert.isTrue(success) - }) - - it('should increment the vote totals', async () => { - await governance.votePartially(proposalId, index, yesVotes, 0, 0) - const [yes, ,] = await governance.getVoteTotals(proposalId) - assert.equal(yes.toNumber(), yesVotes) - }) - - it("should set the voter's vote record", async () => { - await governance.votePartially(proposalId, index, yesVotes, 0, 0) - const [recordProposalId, , , yesVotesRecord, noVotesRecord, abstainVotesRecord] = - await governance.getVoteRecord(account, index) - assertEqualBN(recordProposalId, proposalId) - assertEqualBN(yesVotesRecord, yesVotes) - assertEqualBN(noVotesRecord, 0) - assertEqualBN(abstainVotesRecord, 0) - }) - - it('should set the most recent referendum proposal voted on', async () => { - await governance.votePartially(proposalId, index, yesVotes, 0, 0) - assert.equal( - (await governance.getMostRecentReferendumProposal(account)).toNumber(), - proposalId - ) - }) - - it('should emit the ProposalVotedV2 event', async () => { - await governance.dequeueProposalsIfReady() - const resp = await governance.votePartially(proposalId, index, yesVotes, 0, 0) - assert.equal(resp.logs.length, resp.logs.length) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ProposalVotedV2', - args: { - proposalId: new BigNumber(proposalId), - account, - yesVotes: new BigNumber(yesVotes), - noVotes: new BigNumber(0), - abstainVotes: new BigNumber(0), - }, - }) - }) - - it('should revert when the account weight is 0', async () => { - await mockLockedGold.setAccountTotalGovernancePower(account, 0) - await assertTransactionRevertWithReason( - governance.votePartially(proposalId, index, yesVotes, 0, 0) - ) - }) - - it('should revert when the index is out of bounds', async () => { - await assertTransactionRevertWithReason( - governance.votePartially(proposalId, index + 1, yesVotes, 0, 0), - 'Provided index greater than dequeue length.' - ) - }) - - it('should revert if the proposal id does not match the index', async () => { - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - const otherProposalId = 2 - await assertTransactionRevertWithReason( - governance.votePartially(otherProposalId, index, yesVotes, 0, 0), - 'Proposal not dequeued' - ) - }) - }) - - describe('When voting on different proposal with same index', () => { - const proposalId2 = 2 - const otherAccountWeight = 100 - beforeEach(async () => { - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - await governance.approve(proposalId, index) - await mockLockedGold.setAccountTotalGovernancePower(account, yesVotes) - await governance.votePartially(proposalId, index, yesVotes, 0, 0) - await timeTravel(referendumStageDuration, web3) - await timeTravel(executionStageDuration, web3) - }) - - it('should ignore votes from previous proposal', async () => { - const dequeuedProposal1Dequeued = await governance.dequeued(index) - assertEqualBN(dequeuedProposal1Dequeued, proposalId) - - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await governance.execute(proposalId, index) - assert.isFalse(await governance.proposalExists(proposalId)) - - await timeTravel(dequeueFrequency + 1, web3) - await governance.dequeueProposalsIfReady() - await governance.approve.call(proposalId2, index) - assert.isTrue(await governance.proposalExists(proposalId2)) - - const dequeuedProposal2 = await governance.dequeued(index) - assertEqualBN(dequeuedProposal2, proposalId2) - await governance.getVoteTotals(proposalId2) - - const otherAccount1 = accounts[1] - await accountsInstance.createAccount({ from: otherAccount1 }) - await mockLockedGold.setAccountTotalGovernancePower(otherAccount1, otherAccountWeight) - await governance.votePartially(proposalId2, index, otherAccountWeight, 0, 0, { - from: otherAccount1, - }) - - await governance.votePartially(proposalId2, index, 0, yesVotes, 0) - - const [yesVotesRecord, noVotesRecord, abstainVotesRecord] = await governance.getVoteTotals( - proposalId2 - ) - - assertEqualBN(yesVotesRecord, otherAccountWeight) - assertEqualBN(noVotesRecord, yesVotes) - assertEqualBN(abstainVotesRecord, 0) - }) - }) - }) - - describe('#execute()', () => { - const proposalId = 1 - const index = 0 - const value = VoteValue.Yes - - describe('when executing a proposal with one transaction', () => { - describe('when the proposal can execute successfully', () => { - beforeEach(async () => { - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - await governance.approve(proposalId, index) - await mockLockedGold.setAccountTotalGovernancePower(account, yesVotes) - await governance.vote(proposalId, index, value) - await timeTravel(referendumStageDuration, web3) - }) - - it('should return true', async () => { - const success = await governance.execute.call(proposalId, index) - assert.isTrue(success) - }) - - it('should execute the proposal', async () => { - await governance.execute(proposalId, index) - assert.equal(await testTransactions.getValue(1).valueOf(), 1) - }) - - it('should delete the proposal', async () => { - await governance.execute(proposalId, index) - assert.isFalse(await governance.proposalExists(proposalId)) - }) - - it('should update the participation baseline', async () => { - await governance.execute(proposalId, index) - const [actualParticipationBaseline, , ,] = await governance.getParticipationParameters() - assertEqualBN(actualParticipationBaseline, expectedParticipationBaseline) - }) - - it('should emit the ProposalExecuted event', async () => { - const resp = await governance.execute(proposalId, index) - assert.equal(resp.logs.length, 2) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ProposalExecuted', - args: { - proposalId: new BigNumber(proposalId), - }, - }) - }) - - it('should emit the ParticipationBaselineUpdated event', async () => { - const resp = await governance.execute(proposalId, index) - assert.equal(resp.logs.length, 2) - const log = resp.logs[1] - assertLogMatches2(log, { - event: 'ParticipationBaselineUpdated', - args: { - participationBaseline: expectedParticipationBaseline, - }, - }) - }) - - it('should revert when the index is out of bounds', async () => { - await assertTransactionRevertWithReason( - governance.execute(proposalId, index + 1), - 'Provided index greater than dequeue length.' - ) - }) - }) - - describe('when the proposal can execute successfully - approved in execution stage', () => { - beforeEach(async () => { - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - await mockLockedGold.setAccountTotalGovernancePower(account, yesVotes) - await governance.vote(proposalId, index, value) - await timeTravel(referendumStageDuration + 1, web3) - await governance.approve(proposalId, index) - }) - - it('should return true', async () => { - const success = await governance.execute.call(proposalId, index) - assert.isTrue(success) - }) - - it('should execute the proposal', async () => { - await governance.execute(proposalId, index) - assert.equal(await testTransactions.getValue(1).valueOf(), 1) - }) - - it('should delete the proposal', async () => { - await governance.execute(proposalId, index) - assert.isFalse(await governance.proposalExists(proposalId)) - }) - - it('should update the participation baseline', async () => { - await governance.execute(proposalId, index) - const [actualParticipationBaseline, , ,] = await governance.getParticipationParameters() - assertEqualBN(actualParticipationBaseline, expectedParticipationBaseline) - }) - - it('should emit the ProposalExecuted event', async () => { - const resp = await governance.execute(proposalId, index) - assert.equal(resp.logs.length, 2) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ProposalExecuted', - args: { - proposalId: new BigNumber(proposalId), - }, - }) - }) - - it('should emit the ParticipationBaselineUpdated event', async () => { - const resp = await governance.execute(proposalId, index) - assert.equal(resp.logs.length, 2) - const log = resp.logs[1] - assertLogMatches2(log, { - event: 'ParticipationBaselineUpdated', - args: { - participationBaseline: expectedParticipationBaseline, - }, - }) - }) - - it('should revert when the index is out of bounds', async () => { - await assertTransactionRevertWithReason( - governance.execute(proposalId, index + 1), - 'Provided index greater than dequeue length.' - ) - }) - }) - - describe('when the proposal cannot execute successfully because it is not approved', () => { - beforeEach(async () => { - await governance.propose( - [transactionFail.value], - [transactionFail.destination], - // @ts-ignore bytes type - transactionFail.data, - [transactionFail.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - await mockLockedGold.setAccountTotalGovernancePower(account, yesVotes) - await governance.vote(proposalId, index, value) - await timeTravel(referendumStageDuration, web3) - }) - - it('should revert', async () => { - await assertTransactionRevertWithReason( - governance.execute(proposalId, index), - 'Proposal not approved' - ) - }) - }) - - describe('when the proposal cannot execute successfully', () => { - beforeEach(async () => { - await governance.propose( - [transactionFail.value], - [transactionFail.destination], - // @ts-ignore bytes type - transactionFail.data, - [transactionFail.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - await governance.approve(proposalId, index) - await mockLockedGold.setAccountTotalGovernancePower(account, yesVotes) - await governance.vote(proposalId, index, value) - await timeTravel(referendumStageDuration, web3) - }) - - it('should revert', async () => { - await assertTransactionRevertWithReason( - governance.execute(proposalId, index), - 'Proposal execution failed' - ) - }) - }) - - describe('when the proposal cannot execute because it is not a contract address', () => { - beforeEach(async () => { - await governance.propose( - [transactionSuccess1.value], - [accounts[1]], - // @ts-ignore - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - await governance.approve(proposalId, index) - await mockLockedGold.setAccountTotalGovernancePower(account, yesVotes) - await governance.vote(proposalId, index, value) - await timeTravel(referendumStageDuration, web3) - }) - - it('should revert', async () => { - await assertTransactionRevertWithReason( - governance.execute(proposalId, index), - 'Invalid contract address' - ) - }) - }) - }) - - describe('when executing a proposal with two transactions', () => { - describe('when the proposal can execute successfully', () => { - beforeEach(async () => { - await governance.propose( - [transactionSuccess1.value, transactionSuccess2.value], - [transactionSuccess1.destination, transactionSuccess2.destination], - // @ts-ignore - Buffer.concat([transactionSuccess1.data, transactionSuccess2.data]), - [transactionSuccess1.data.length, transactionSuccess2.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - await governance.approve(proposalId, index) - await mockLockedGold.setAccountTotalGovernancePower(account, yesVotes) - await governance.vote(proposalId, index, value) - await timeTravel(referendumStageDuration, web3) - }) - - it('should return true', async () => { - const success = await governance.execute.call(proposalId, index) - assert.isTrue(success) - }) - - it('should execute the proposal', async () => { - await governance.execute(proposalId, index) - assert.equal(await testTransactions.getValue(1).valueOf(), 1) - assert.equal(await testTransactions.getValue(2).valueOf(), 1) - }) - - it('should delete the proposal', async () => { - await governance.execute(proposalId, index) - assert.isFalse(await governance.proposalExists(proposalId)) - }) - - it('should update the participation baseline', async () => { - await governance.execute(proposalId, index) - const [actualParticipationBaseline, , ,] = await governance.getParticipationParameters() - assertEqualBN(actualParticipationBaseline, expectedParticipationBaseline) - }) - - it('should emit the ProposalExecuted event', async () => { - const resp = await governance.execute(proposalId, index) - assert.equal(resp.logs.length, 2) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ProposalExecuted', - args: { - proposalId: new BigNumber(proposalId), - }, - }) - }) - - it('should emit the ParticipationBaselineUpdated event', async () => { - const resp = await governance.execute(proposalId, index) - assert.equal(resp.logs.length, 2) - const log = resp.logs[1] - assertLogMatches2(log, { - event: 'ParticipationBaselineUpdated', - args: { - participationBaseline: expectedParticipationBaseline, - }, - }) - }) - }) - - describe('when the proposal cannot execute successfully', () => { - describe('when the first transaction cannot execute', () => { - beforeEach(async () => { - await governance.propose( - [transactionSuccess1.value, transactionFail.value], - [transactionSuccess1.destination, transactionFail.destination], - // @ts-ignore - Buffer.concat([transactionSuccess1.data, transactionFail.data]), - [transactionSuccess1.data.length, transactionFail.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - await governance.approve(proposalId, index) - await mockLockedGold.setAccountTotalGovernancePower(account, yesVotes) - await governance.vote(proposalId, index, value) - await timeTravel(referendumStageDuration, web3) - }) - - it('should revert', async () => { - await assertTransactionRevertWithReason( - governance.execute(proposalId, index), - 'Proposal execution failed' - ) - }) - }) - - describe('when the second transaction cannot execute', () => { - beforeEach(async () => { - await governance.propose( - [transactionFail.value, transactionSuccess1.value], - [transactionFail.destination, transactionSuccess1.destination], - // @ts-ignore - Buffer.concat([transactionFail.data, transactionSuccess1.data]), - [transactionFail.data.length, transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - await governance.approve(proposalId, index) - await mockLockedGold.setAccountTotalGovernancePower(account, yesVotes) - await governance.vote(proposalId, index, value) - await timeTravel(referendumStageDuration, web3) - }) - - it('should revert', async () => { - await assertTransactionRevertWithReason( - governance.execute(proposalId, index), - 'Proposal execution failed' - ) - }) - }) - }) - }) - - describe('when the proposal is past the execution stage', () => { - beforeEach(async () => { - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - await governance.approve(proposalId, index) - await mockLockedGold.setAccountTotalGovernancePower(account, yesVotes) - await governance.vote(proposalId, index, value) - await timeTravel(referendumStageDuration, web3) - await timeTravel(executionStageDuration, web3) - }) - - it('should return false', async () => { - const success = await governance.execute.call(proposalId, index) - assert.isFalse(success) - }) - - it('should delete the proposal', async () => { - await governance.execute(proposalId, index) - assert.isFalse(await governance.proposalExists(proposalId)) - }) - - it('should remove the proposal ID from dequeued', async () => { - await governance.execute(proposalId, index) - const dequeued = await governance.getDequeue() - assert.notInclude( - dequeued.map((x) => x.toNumber()), - proposalId - ) - }) - - it('should add the index to empty indices', async () => { - await governance.execute(proposalId, index) - const emptyIndex = await governance.emptyIndices(0) - assert.equal(emptyIndex.toNumber(), index) - }) - - it('should update the participation baseline', async () => { - await governance.execute(proposalId, index) - const [actualParticipationBaseline, , ,] = await governance.getParticipationParameters() - assertEqualBN(actualParticipationBaseline, expectedParticipationBaseline) - }) - - it('should emit the ParticipationBaselineUpdated event', async () => { - const resp = await governance.execute(proposalId, index) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ParticipationBaselineUpdated', - args: { - participationBaseline: expectedParticipationBaseline, - }, - }) - }) - }) - - describe('when a proposal with 0 transactions is past the execution stage', () => { - beforeEach(async () => { - await governance.propose( - [], - [], - // @ts-ignore - [], - [], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - await mockLockedGold.setAccountTotalGovernancePower(account, yesVotes) - }) - - it('should not emit ProposalExecuted when not approved', async () => { - await governance.vote(proposalId, index, value) - await timeTravel(referendumStageDuration, web3) - await timeTravel(executionStageDuration, web3) - const resp = await governance.execute(proposalId, index) - assert.isTrue( - resp.logs.every((log) => log.event !== 'ProposalExecuted'), - 'ProposalExecuted should not be emitted' - ) - }) - - it('should not emit ProposalExecuted when not passing', async () => { - await governance.approve(proposalId, index) - await timeTravel(referendumStageDuration, web3) - await timeTravel(executionStageDuration, web3) - const resp = await governance.execute(proposalId, index) - assert.isTrue( - resp.logs.every((log) => log.event !== 'ProposalExecuted'), - 'ProposalExecuted should not be emitted' - ) - }) - - describe('Proposal approved and passing', () => { - beforeEach(async () => { - await governance.approve(proposalId, index) - await governance.vote(proposalId, index, value) - await timeTravel(referendumStageDuration, web3) - await timeTravel(executionStageDuration, web3) - }) - - it('should return true', async () => { - const success = await governance.execute.call(proposalId, index) - assert.isTrue(success) - }) - - it('should delete the proposal', async () => { - await governance.execute(proposalId, index) - assert.isFalse(await governance.proposalExists(proposalId)) - }) - - it('should remove the proposal ID from dequeued', async () => { - await governance.execute(proposalId, index) - const dequeued = await governance.getDequeue() - assert.notInclude( - dequeued.map((x) => x.toNumber()), - proposalId - ) - }) - - it('should add the index to empty indices', async () => { - await governance.execute(proposalId, index) - const emptyIndex = await governance.emptyIndices(0) - assert.equal(emptyIndex.toNumber(), index) - }) - - it('should update the participation baseline', async () => { - await governance.execute(proposalId, index) - const [actualParticipationBaseline, , ,] = await governance.getParticipationParameters() - assertEqualBN(actualParticipationBaseline, expectedParticipationBaseline) - }) - - it('should emit ProposalExecuted and ParticipationBaselineUpdated event', async () => { - const resp = await governance.execute(proposalId, index) - assert.equal(resp.logs.length, 2) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ProposalExecuted', - args: { - proposalId: new BigNumber(proposalId), - }, - }) - const log2 = resp.logs[1] - assertLogMatches2(log2, { - event: 'ParticipationBaselineUpdated', - args: { - participationBaseline: expectedParticipationBaseline, - }, - }) - }) - }) - }) - }) - - describe('#approveHotfix()', () => { - it('should mark the hotfix record approved when called by approver', async () => { - await governance.approveHotfix(hotfixHashStr, { from: approver }) - const [approved, ,] = await governance.getHotfixRecord.call(hotfixHashStr) - assert.isTrue(approved) - }) - - it('should emit the HotfixApproved event', async () => { - const resp = await governance.approveHotfix(hotfixHashStr, { from: approver }) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'HotfixApproved', - args: { - hash: matchAny, - }, - }) - assert.isTrue(Buffer.from(stripHexEncoding(log.args.hash), 'hex').equals(hotfixHash)) - }) - - it('should revert when called by non-approver', async () => { - await assertTransactionRevertWithReason( - governance.approveHotfix(hotfixHashStr, { from: accounts[2] }), - 'msg.sender not approver' - ) - }) - }) - - describe('#whitelistHotfix()', () => { - beforeEach(async () => { - // from GovernanceTest - await governance.addValidator(accounts[2]) - await governance.addValidator(accounts[3]) - }) - - it('should emit the HotfixWhitelist event', async () => { - const resp = await governance.whitelistHotfix(hotfixHashStr, { from: accounts[3] }) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'HotfixWhitelisted', - args: { - hash: matchAny, - whitelister: accounts[3], - }, - }) - assert.isTrue(Buffer.from(stripHexEncoding(log.args.hash), 'hex').equals(hotfixHash)) - }) - }) - - describe('#hotfixWhitelistValidatorTally', () => { - const newHotfixHash = bufferToHex(toBuffer(keccak256(utf8ToBytes('celo bug fix')))) - - const validators = zip( - (_account, signer) => ({ account: _account, signer }), - accounts.slice(2, 5), - accounts.slice(5, 8) - ) - - beforeEach(async () => { - for (const validator of validators) { - await accountsInstance.createAccount({ from: validator.account }) - const sig = await getParsedSignatureOfAddress(web3, validator.account, validator.signer) - await accountsInstance.authorizeValidatorSigner(validator.signer, sig.v, sig.r, sig.s, { - from: validator.account, - }) - // add signers for mock precompile - await governance.addValidator(validator.signer) - } - }) - - const whitelistFrom = (t: keyof (typeof validators)[0]) => - concurrentMap(5, validators, (v) => governance.whitelistHotfix(newHotfixHash, { from: v[t] })) - - const checkTally = async () => { - const tally = await governance.hotfixWhitelistValidatorTally(newHotfixHash) - assert.equal(tally.toNumber(), validators.length) - } - - it('should count validator accounts that have whitelisted', async () => { - await whitelistFrom('account') - await checkTally() - }) - - it('should count authorized validator signers that have whitelisted', async () => { - await whitelistFrom('signer') - await checkTally() - }) - - it('should not double count validator account and authorized signer accounts', async () => { - await whitelistFrom('signer') - await whitelistFrom('account') - await checkTally() - }) - - it('should return the correct tally after key rotation', async () => { - await whitelistFrom('signer') - const newSigner = accounts[9] - const sig = await getParsedSignatureOfAddress(web3, validators[0].account, newSigner) - await accountsInstance.authorizeValidatorSigner(newSigner, sig.v, sig.r, sig.s, { - from: validators[0].account, - }) - await checkTally() - }) - }) - - describe('#isHotfixPassing', () => { - beforeEach(async () => { - await governance.addValidator(accounts[2]) - await governance.addValidator(accounts[3]) - await accountsInstance.createAccount({ from: accounts[2] }) - await accountsInstance.createAccount({ from: accounts[3] }) - }) - - it('should return false when hotfix has not been whitelisted', async () => { - const passing = await governance.isHotfixPassing.call(hotfixHashStr) - assert.isFalse(passing) - }) - - it('should return false when hotfix has been whitelisted but not by quorum', async () => { - await governance.whitelistHotfix(hotfixHashStr, { from: accounts[2] }) - const passing = await governance.isHotfixPassing.call(hotfixHashStr) - assert.isFalse(passing) - }) - - it('should return true when hotfix is whitelisted by quorum', async () => { - await governance.whitelistHotfix(hotfixHashStr, { from: accounts[2] }) - await governance.whitelistHotfix(hotfixHashStr, { from: accounts[3] }) - const passing = await governance.isHotfixPassing.call(hotfixHashStr) - assert.isTrue(passing) - }) - }) - - describe('#prepareHotfix()', () => { - beforeEach(async () => { - await governance.addValidator(accounts[2]) - await accountsInstance.createAccount({ from: accounts[2] }) - }) - - it('should revert when hotfix is not passing', async () => { - await assertTransactionRevertWithReason( - governance.prepareHotfix(hotfixHashStr), - 'hotfix not whitelisted by 2f[+]1 validators' - ) - }) - - describe('when hotfix is passing', () => { - beforeEach(async () => { - await mineToNextEpoch(web3) - await governance.whitelistHotfix(hotfixHashStr, { from: accounts[2] }) - }) - - it('should mark the hotfix record prepared epoch', async () => { - await governance.prepareHotfix(hotfixHashStr) - const [, , preparedEpoch] = await governance.getHotfixRecord.call(hotfixHashStr) - const currEpoch = new BigNumber(await governance.getEpochNumber()) - assertEqualBN(preparedEpoch, currEpoch) - }) - - it('should emit the HotfixPrepared event', async () => { - const resp = await governance.prepareHotfix(hotfixHashStr) - const currEpoch = new BigNumber(await governance.getEpochNumber()) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'HotfixPrepared', - args: { - hash: matchAny, - epoch: currEpoch, - }, - }) - assert.isTrue(Buffer.from(stripHexEncoding(log.args.hash), 'hex').equals(hotfixHash)) - }) - - it('should revert when epoch == preparedEpoch', async () => { - await governance.prepareHotfix(hotfixHashStr) - await assertTransactionRevertWithReason( - governance.prepareHotfix(hotfixHashStr), - 'hotfix already prepared for this epoch' - ) - }) - - it('should succeed for epoch != preparedEpoch', async () => { - await governance.prepareHotfix(hotfixHashStr) - await mineToNextEpoch(web3) - await governance.prepareHotfix(hotfixHashStr) - }) - }) - }) - - describe('#executeHotfix()', () => { - const executeHotfixTx = () => { - return governance.executeHotfix( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - salt - ) - } - - it('should revert when hotfix not approved', async () => { - await assertTransactionRevertWithReason(executeHotfixTx(), 'hotfix not approved') - }) - - it('should revert when hotfix not prepared for current epoch', async () => { - await mineToNextEpoch(web3) - await governance.approveHotfix(hotfixHashStr, { from: approver }) - await assertTransactionRevertWithReason( - executeHotfixTx(), - 'hotfix must be prepared for this epoch' - ) - }) - - it('should revert when hotfix prepared but not for current epoch', async () => { - await governance.approveHotfix(hotfixHashStr, { from: approver }) - await governance.addValidator(accounts[2]) - await accountsInstance.createAccount({ from: accounts[2] }) - await governance.whitelistHotfix(hotfixHashStr, { from: accounts[2] }) - await governance.prepareHotfix(hotfixHashStr, { from: accounts[2] }) - await mineToNextEpoch(web3) - await assertTransactionRevertWithReason( - executeHotfixTx(), - 'hotfix must be prepared for this epoch' - ) - }) - - describe('when hotfix is approved and prepared for current epoch', () => { - beforeEach(async () => { - await governance.approveHotfix(hotfixHashStr, { from: approver }) - await mineToNextEpoch(web3) - await governance.addValidator(accounts[2]) - await accountsInstance.createAccount({ from: accounts[2] }) - await governance.whitelistHotfix(hotfixHashStr, { from: accounts[2] }) - await governance.prepareHotfix(hotfixHashStr) - }) - - it('should execute the hotfix tx', async () => { - await executeHotfixTx() - assert.equal(await testTransactions.getValue(1).valueOf(), 1) - }) - - it('should mark the hotfix record as executed', async () => { - await executeHotfixTx() - const [, executed] = await governance.getHotfixRecord.call(hotfixHashStr) - assert.isTrue(executed) - }) - - it('should emit the HotfixExecuted event', async () => { - const resp = await executeHotfixTx() - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'HotfixExecuted', - args: { - hash: matchAny, - }, - }) - assert.isTrue(Buffer.from(stripHexEncoding(log.args.hash), 'hex').equals(hotfixHash)) - }) - - it('should not be executable again', async () => { - await executeHotfixTx() - await assertTransactionRevertWithReason(executeHotfixTx(), 'hotfix already executed') - }) - }) - }) - - describe('#isVoting()', () => { - describe('when the account has never acted on a proposal', () => { - it('should return false', async () => { - assert.isFalse(await governance.isVoting(account)) - }) - }) - - describe('when the account has upvoted a proposal', () => { - const proposalId = 1 - beforeEach(async () => { - await mockLockedGold.setAccountTotalLockedGold(account, yesVotes) - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await governance.upvote(proposalId, 0, 0) - }) - - it('should return true', async () => { - assert.isTrue(await governance.isVoting(account)) - }) - - describe('when that upvote has been revoked', () => { - beforeEach(async () => { - await governance.revokeUpvote(0, 0) - }) - - it('should return false', async () => { - assert.isFalse(await governance.isVoting(account)) - }) - }) - - describe('when that proposal has expired from the queue', () => { - beforeEach(async () => { - await timeTravel(queueExpiry, web3) - }) - - it('should return false', async () => { - assert.isFalse(await governance.isVoting(account)) - }) - }) - }) - - describe('when the account has voted on a proposal', () => { - const proposalId = 1 - const index = 0 - const value = VoteValue.Abstain - beforeEach(async () => { - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - await governance.approve(proposalId, index) - await mockLockedGold.setAccountTotalGovernancePower(account, yesVotes) - await governance.vote(proposalId, index, value) - }) - - it('should return true', async () => { - assert.isTrue(await governance.isVoting(account)) - }) - - describe('when that proposal is no longer in the referendum stage', () => { - beforeEach(async () => { - await timeTravel(referendumStageDuration, web3) - }) - - it('should return false', async () => { - assert.isFalse(await governance.isVoting(account)) - }) - }) - }) - }) - - describe('#isProposalPassing()', () => { - const proposalId = 1 - const index = 0 - beforeEach(async () => { - await accountsInstance.createAccount({ from: otherAccount }) - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - await governance.approve(proposalId, index) - }) - - describe('when the adjusted support is greater than threshold', () => { - beforeEach(async () => { - await mockLockedGold.setAccountTotalGovernancePower(account, (yesVotes * 51) / 100) - await mockLockedGold.setAccountTotalGovernancePower(otherAccount, (yesVotes * 49) / 100) - await governance.vote(proposalId, index, VoteValue.Yes) - await governance.vote(proposalId, index, VoteValue.No, { from: otherAccount }) - }) - - it('should return true', async () => { - const passing = await governance.isProposalPassing(proposalId) - assert.isTrue(passing) - }) - }) - - describe('when the adjusted support is less than or equal to threshold', () => { - beforeEach(async () => { - await mockLockedGold.setAccountTotalGovernancePower(account, (yesVotes * 50) / 100) - await mockLockedGold.setAccountTotalGovernancePower(otherAccount, (yesVotes * 50) / 100) - await governance.vote(proposalId, index, VoteValue.Yes) - await governance.vote(proposalId, index, VoteValue.No, { from: otherAccount }) - }) - - it('should return false', async () => { - const passing = await governance.isProposalPassing(proposalId) - assert.isFalse(passing) - }) - }) - }) - - describe('#dequeueProposalsIfReady()', () => { - it('should not update lastDequeue when there are no queued proposals', async () => { - const originalLastDequeue = await governance.lastDequeue() - await timeTravel(dequeueFrequency, web3) - await governance.dequeueProposalsIfReady() - - assert.equal((await governance.getQueueLength()).toNumber(), 0) - assert.equal((await governance.lastDequeue()).toNumber(), originalLastDequeue.toNumber()) - }) - - describe('when a proposal exists', () => { - beforeEach(async () => { - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - { value: minDeposit } - ) - }) - - it('should update lastDequeue', async () => { - const originalLastDequeue = await governance.lastDequeue() - - await timeTravel(dequeueFrequency, web3) - await governance.dequeueProposalsIfReady() - - assert.equal((await governance.getQueueLength()).toNumber(), 0) - assert.isTrue((await governance.lastDequeue()).toNumber() > originalLastDequeue.toNumber()) - }) - - it('should not update lastDequeue when only expired proposal queued', async () => { - const originalLastDequeue = await governance.lastDequeue() - - await timeTravel(queueExpiry, web3) - await governance.dequeueProposalsIfReady() - - assert.equal((await governance.getQueueLength()).toNumber(), 0) - assert.equal((await governance.lastDequeue()).toNumber(), originalLastDequeue.toNumber()) - }) - }) - }) - - describe('#getProposalStage()', () => { - const expectStage = async (expected: Stage, _proposalId: number) => { - const stage = await governance.getProposalStage(_proposalId) - assertEqualBN(stage, expected) - } - - it('should return None stage when proposal does not exist', async () => { - await expectStage(Stage.None, 0) - await expectStage(Stage.None, 1) - }) - - describe('when proposal exists', () => { - let proposalId: number - beforeEach(async () => { - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - { value: minDeposit } - ) - proposalId = 1 - const exists = await governance.proposalExists(proposalId) - assert.isTrue(exists, 'proposal does not exist') - }) - - describe('when proposal is queued', () => { - beforeEach(async () => { - const queued = await governance.isQueued(proposalId) - assert.isTrue(queued, 'proposal not queued') - }) - - it('should return Queued when not expired', () => expectStage(Stage.Queued, proposalId)) - - it('should return Expiration when expired', async () => { - await timeTravel(queueExpiry, web3) - await expectStage(Stage.Expiration, proposalId) - }) - }) - - describe('when proposal is dequeued', () => { - const index = 0 - beforeEach(async () => { - await timeTravel(dequeueFrequency, web3) - await governance.dequeueProposalsIfReady() - const dequeued = await governance.isDequeuedProposal(proposalId, index) - assert.isTrue(dequeued, 'proposal not dequeued') - }) - - describe('when in referendum stage', () => { - describe('when not approved', () => { - it('should return Referendum when not voted and not expired', () => - expectStage(Stage.Referendum, proposalId)) - - it('should return Expiration when expired', async () => { - await timeTravel(referendumStageDuration, web3) - await expectStage(Stage.Expiration, proposalId) - }) - }) - - describe('when approved', () => { - beforeEach(async () => { - await governance.approve(proposalId, index) - }) - - it('should return Referendum when not expired', () => - expectStage(Stage.Referendum, proposalId)) - - it('should return Expiration when expired', async () => { - await timeTravel(referendumStageDuration, web3) - await expectStage(Stage.Expiration, proposalId) - }) - }) - }) - - describe('when in execution stage', () => { - beforeEach(async () => { - await governance.approve(proposalId, index) - await governance.vote(proposalId, index, VoteValue.Yes) - const passing = await governance.isProposalPassing(proposalId) - assert.isTrue(passing, 'proposal not passing') - await timeTravel(referendumStageDuration, web3) - }) - - it('should return Execution when not expired', () => - expectStage(Stage.Execution, proposalId)) - - it('should return Expiration when expired', async () => { - await timeTravel(executionStageDuration, web3) - await expectStage(Stage.Expiration, proposalId) - const isDequeuedProposalExpired = await governance.isDequeuedProposalExpired(proposalId) - assert.isTrue(isDequeuedProposalExpired) - }) - }) - }) - }) - - describe('when a proposal with 0 transactions exists', () => { - let proposalId: number - beforeEach(async () => { - await governance.propose( - [], - [], - // @ts-ignore - [], - [], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - proposalId = 1 - const exists = await governance.proposalExists(proposalId) - assert.isTrue(exists, 'proposal does not exist') - }) - - describe('when proposal with 0 transactions is dequeued', () => { - const index = 0 - beforeEach(async () => { - await timeTravel(dequeueFrequency, web3) - await governance.dequeueProposalsIfReady() - const dequeued = await governance.isDequeuedProposal(proposalId, index) - assert.isTrue(dequeued, 'proposal not dequeued') - }) - - it('should return Expiration past the execution stage when not approved', async () => { - await governance.vote(proposalId, index, VoteValue.Yes) - await timeTravel(referendumStageDuration + executionStageDuration + 1, web3) - await expectStage(Stage.Expiration, proposalId) - const isDequeuedProposalExpired = await governance.isDequeuedProposalExpired(proposalId) - assert.isTrue(isDequeuedProposalExpired) - }) - - it('should return Expiration past the execution stage when not passing', async () => { - await governance.approve(proposalId, index) - await timeTravel(referendumStageDuration + executionStageDuration + 1, web3) - await expectStage(Stage.Expiration, proposalId) - const isDequeuedProposalExpired = await governance.isDequeuedProposalExpired(proposalId) - assert.isTrue(isDequeuedProposalExpired) - }) - - describe('when in execution stage', () => { - beforeEach(async () => { - await governance.approve(proposalId, index) - await governance.vote(proposalId, index, VoteValue.Yes) - const passing = await governance.isProposalPassing(proposalId) - assert.isTrue(passing, 'proposal not passing') - await timeTravel(referendumStageDuration, web3) - }) - - it('should return Execution when not expired', () => - expectStage(Stage.Execution, proposalId)) - - it('should return Execution past the execution stage if passed and approved', async () => { - await timeTravel(executionStageDuration + 1, web3) - await expectStage(Stage.Execution, proposalId) - const isDequeuedProposalExpired = await governance.isDequeuedProposalExpired(proposalId) - assert.isFalse(isDequeuedProposalExpired) - }) - }) - }) - }) - }) - - describe('#getAmountOfGoldUsedForVoting()', () => { - describe('3 concurrent proposals dequeued', () => { - beforeEach(async () => { - await governance.setConcurrentProposals(3) - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await governance.propose( - [transactionSuccess2.value], - [transactionSuccess2.destination], - // @ts-ignore bytes type - transactionSuccess2.data, - [transactionSuccess2.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - await governance.approve(1, 0) - await governance.approve(2, 1) - await governance.approve(3, 2) - await mockLockedGold.setAccountTotalGovernancePower(account, yesVotes) - }) - for (let numVoted = 0; numVoted < 3; numVoted++) { - describe(`when account has partially voted on ${numVoted} proposals`, () => { - const yes = 10 - const no = 30 - const abstain = 0 - - beforeEach(async () => { - for (let i = 0; i < numVoted; i++) { - await governance.votePartially(1, 0, yes, no, abstain) - } - }) - - it('Should return correct number of votes', async () => { - const totalVotesByAccount = await governance.getAmountOfGoldUsedForVoting(accounts[0]) - const expectedArraySum = yes + no + abstain - assertEqualBN(totalVotesByAccount, numVoted === 0 ? 0 : expectedArraySum) - }) - }) - } - }) - - describe('proposal dequeued', () => { - beforeEach(async () => { - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await timeTravel(dequeueFrequency, web3) - await governance.approve(1, 0) - await mockLockedGold.setAccountTotalGovernancePower(account, yesVotes) - }) - - describe('When account voted on proposal in V8', () => { - beforeEach(async () => { - await governance.setDeprecatedWeight(accounts[0], 0, 100) - }) - - it('Should return correct number of votes', async () => { - const totalVotesByAccount = await governance.getAmountOfGoldUsedForVoting(accounts[0]) - assertEqualBN(totalVotesByAccount, 100) - }) - }) - - describe(`when account has partially voted on proposal`, () => { - const yes = 10 - const no = 30 - const abstain = 0 - - beforeEach(async () => { - await governance.votePartially(1, 0, yes, no, abstain) - }) - - it('Should return correct number of votes', async () => { - const totalVotesByAccount = await governance.getAmountOfGoldUsedForVoting(accounts[0]) - const expectedArraySum = yes + no + abstain - - assertEqualBN(totalVotesByAccount, expectedArraySum) - }) - - it('Should return 0 votes since expired', async () => { - await timeTravel(executionStageDuration + referendumStageDuration + 1, web3) - const totalVotesByAccount = await governance.getAmountOfGoldUsedForVoting(accounts[0]) - - assertEqualBN(totalVotesByAccount, 0) - }) - }) - }) - - describe('proposal in queue', () => { - beforeEach(async () => { - const proposalId1 = 1 - - await governance.setConcurrentProposals(3) - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - await mockLockedGold.setAccountTotalLockedGold(account, yesVotes) - await governance.upvote(proposalId1, 0, 0) - }) - - it('should return full weight when upvoting', async () => { - const totalVotesByAccount = await governance.getAmountOfGoldUsedForVoting(accounts[0]) - assertEqualBN(totalVotesByAccount, yesVotes) - }) - - it('should return 0 since proposal is already expired', async () => { - await timeTravel(queueExpiry, web3) - const totalVotesByAccount = await governance.getAmountOfGoldUsedForVoting(accounts[0]) - assertEqualBN(totalVotesByAccount, 0) - }) - }) - }) - - describe('#removeVotesWhenRevokingDelegatedVotes()', () => { - it('should revert when not called by staked celo contract', async () => { - await assertTransactionRevertWithReason( - governance.removeVotesWhenRevokingDelegatedVotes(NULL_ADDRESS, 0), - 'msg.sender not lockedGold' - ) - }) - - it('should should pass when no proposal is dequeued', async () => { - await governance.removeVotesWhenRevokingDelegatedVotesTest(NULL_ADDRESS, 0) - }) - - describe('When having three proposals voted', () => { - const proposalId = 1 - const index = 0 - - const proposal2Id = 2 - const index2 = 1 - - const proposal3Id = 3 - const index3 = 2 - beforeEach(async () => { - const newDequeueFrequency = 60 - await governance.setDequeueFrequency(newDequeueFrequency) - - await governance.propose( - [transactionSuccess1.value], - [transactionSuccess1.destination], - // @ts-ignore bytes type - transactionSuccess1.data, - [transactionSuccess1.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - - await governance.propose( - [transactionSuccess2.value], - [transactionSuccess2.destination], - // @ts-ignore bytes type - transactionSuccess2.data, - [transactionSuccess2.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - - await governance.propose( - [transactionSuccess2.value], - [transactionSuccess2.destination], - // @ts-ignore bytes type - transactionSuccess2.data, - [transactionSuccess2.data.length], - descriptionUrl, - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - { value: minDeposit } - ) - - await governance.setConcurrentProposals(3) - await timeTravel(newDequeueFrequency, web3) - await governance.approve(proposalId, index) - await timeTravel(newDequeueFrequency, web3) - await governance.approve(proposal2Id, index2) - await timeTravel(newDequeueFrequency, web3) - await governance.approve(proposal3Id, index3) - await mockLockedGold.setAccountTotalGovernancePower(account, yesVotes) - }) - - describe('When voting only for yes', () => { - const yes = 100 - const no = 0 - const abstain = 0 - - const yes2 = 0 - const no2 = 100 - const abstain2 = 0 - beforeEach(async () => { - await governance.votePartially(proposalId, index, yes, no, abstain) - await governance.votePartially(proposal2Id, index2, yes2, no2, abstain2) - - await assertVoteRecord(governance, account, index, proposalId, yes, no, abstain) - await assertVoteRecord(governance, account, index2, proposal2Id, yes2, no2, abstain2) - - await assertVotesTotal(governance, proposalId, yes, no, abstain) - await assertVotesTotal(governance, proposal2Id, yes2, no2, abstain2) - }) - - it('should adjust votes correctly to 0', async () => { - const maxAmount = 0 - - await governance.removeVotesWhenRevokingDelegatedVotesTest(account, maxAmount) - - await assertVoteRecord(governance, account, index, proposalId, 0, 0, 0) - await assertVoteRecord(governance, account, index2, proposal2Id, 0, 0, 0) - - await assertVotesTotal(governance, proposalId, 0, 0, 0) - await assertVotesTotal(governance, proposal2Id, 0, 0, 0) - }) - - it('should adjust votes correctly to 30', async () => { - const maxAmount = 30 - - await governance.removeVotesWhenRevokingDelegatedVotesTest(account, maxAmount) - - await assertVoteRecord(governance, account, index, proposalId, maxAmount, 0, 0) - await assertVoteRecord(governance, account, index2, proposal2Id, 0, maxAmount, 0) - - await assertVotesTotal(governance, proposalId, maxAmount, 0, 0) - await assertVotesTotal(governance, proposal2Id, 0, maxAmount, 0) - }) - }) - - describe('When voting for all choices', () => { - const yes = 34 - const no = 33 - const abstain = 33 - - const yes2 = 0 - const no2 = 35 - const abstain2 = 65 - - const yes3 = 0 - const no3 = 0 - const abstain3 = 51 - - beforeEach(async () => { - await governance.votePartially(proposalId, index, yes, no, abstain) - await governance.votePartially(proposal2Id, index2, yes2, no2, abstain2) - await governance.votePartially(proposal3Id, index3, yes3, no3, abstain3) - - await assertVoteRecord(governance, account, index, proposalId, yes, no, abstain) - await assertVoteRecord(governance, account, index2, proposal2Id, yes2, no2, abstain2) - await assertVoteRecord(governance, account, index3, proposal3Id, yes3, no3, abstain3) - }) - - it('should adjust votes correctly to 0', async () => { - const maxAmount = 0 - - await governance.removeVotesWhenRevokingDelegatedVotesTest(account, maxAmount) - - await assertVoteRecord(governance, account, index, proposalId, 0, 0, 0) - await assertVoteRecord(governance, account, index2, proposal2Id, 0, 0, 0) - }) - - it('should adjust votes correctly to 50', async () => { - const maxAmount = 50 - const sumOfVotes = yes + no + abstain - const toRemove = sumOfVotes - maxAmount - const yesPortion = (toRemove * yes) / sumOfVotes - const noPortion = (toRemove * no) / sumOfVotes - const abstainPortion = (toRemove * abstain) / sumOfVotes - - const no2Portion = (toRemove * no2) / sumOfVotes - const abstain2Portion = (toRemove * abstain2) / sumOfVotes - - await governance.removeVotesWhenRevokingDelegatedVotesTest(account, maxAmount) - - const [yes1Total, no1Total, abstain1Total] = await governance.getVoteTotals(proposalId) - const [yes2Total, no2Total, abstain2Total] = await governance.getVoteTotals(proposal2Id) - const [yes3Total, no3Total, abstain3Total] = await governance.getVoteTotals(proposal3Id) - - assertEqualBN(yes1Total.plus(no1Total).plus(abstain1Total), maxAmount) - assertEqualBN(yes2Total.plus(no2Total).plus(abstain2Total), maxAmount) - assertEqualBN(yes3Total.plus(no3Total).plus(abstain3Total), maxAmount) - - assertEqualBN(yes1Total, Math.ceil(yesPortion) - 1) // -1 because of rounding - assertEqualBN(no1Total, Math.ceil(noPortion)) - assertEqualBN(abstain1Total, Math.ceil(abstainPortion)) - - assertEqualBN(yes2Total, 0) - assertEqualBN(no2Total, Math.ceil(no2Portion) - 1) // -1 because of rounding - assertEqualBN(abstain2Total, Math.ceil(abstain2Portion)) - - await assertVoteRecord( - governance, - account, - index, - proposalId, - Math.ceil(yesPortion - 1), // -1 because of rounding - Math.ceil(noPortion), - Math.ceil(abstainPortion) - ) - await assertVoteRecord( - governance, - account, - index2, - proposal2Id, - Math.ceil(0), - Math.ceil(no2Portion - 1), // -1 because of rounding - Math.ceil(abstain2Portion) - ) - }) - - describe('When proposals are expired', () => { - beforeEach(async () => { - await timeTravel(queueExpiry, web3) - }) - - it('should not adjust votes', async () => { - await assertVoteRecord(governance, account, index, proposalId, yes, no, abstain) - await assertVoteRecord(governance, account, index2, proposal2Id, yes2, no2, abstain2) - }) - }) - }) - }) - }) -}) - -async function assertVoteRecord( - governance: GovernanceTestInstance, - account: string, - index: number, - assertId: number, - assertYes: number, - assertNo: number, - asssertAbstain: number -) { - const [recordProposalId2, , , yesVotesRecord2, noVotesRecord2, abstainVotesRecord2] = - await governance.getVoteRecord(account, index) - - assertEqualBN(recordProposalId2, assertId) - assertEqualBN(yesVotesRecord2, assertYes) - assertEqualBN(noVotesRecord2, assertNo) - assertEqualBN(abstainVotesRecord2, asssertAbstain) -} - -async function assertVotesTotal( - governance: GovernanceTestInstance, - proposalId: number, - assertYes: number, - assertNo: number, - assertAbstain: number -) { - const [yesVotes, noVotes, abstainVotes] = await governance.getVoteTotals(proposalId) - assertEqualBN(yesVotes, assertYes) - assertEqualBN(noVotes, assertNo) - assertEqualBN(abstainVotes, assertAbstain) -} diff --git a/packages/protocol/test/governance/network/governance_slasher.ts b/packages/protocol/test/governance/network/governance_slasher.ts deleted file mode 100644 index bb694cf19..000000000 --- a/packages/protocol/test/governance/network/governance_slasher.ts +++ /dev/null @@ -1,120 +0,0 @@ -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { - assertContainSubset, - assertTransactionRevertWithReason, -} from '@celo/protocol/lib/test-utils' -import BigNumber from 'bignumber.js' -import { - AccountsContract, - AccountsInstance, - GovernanceSlasherContract, - GovernanceSlasherInstance, - MockLockedGoldContract, - MockLockedGoldInstance, - MockValidatorsContract, - MockValidatorsInstance, - RegistryContract, - RegistryInstance, -} from 'types' - -const Accounts: AccountsContract = artifacts.require('Accounts') -const MockValidators: MockValidatorsContract = artifacts.require('MockValidators') -const GovernanceSlasher: GovernanceSlasherContract = artifacts.require('GovernanceSlasher') -const MockLockedGold: MockLockedGoldContract = artifacts.require('MockLockedGold') -const Registry: RegistryContract = artifacts.require('Registry') - -// TODO(mcortesi): Use BN -// @ts-ignore -GovernanceSlasher.numberFormat = 'BigNumber' - -contract('GovernanceSlasher', (accounts: string[]) => { - let accountsInstance: AccountsInstance - let validators: MockValidatorsInstance - let registry: RegistryInstance - let mockLockedGold: MockLockedGoldInstance - let slasher: GovernanceSlasherInstance - const nonOwner = accounts[1] - const validator = accounts[1] - - beforeEach(async () => { - accountsInstance = await Accounts.new(true) - await Promise.all(accounts.map((account) => accountsInstance.createAccount({ from: account }))) - mockLockedGold = await MockLockedGold.new() - registry = await Registry.new(true) - validators = await MockValidators.new() - slasher = await GovernanceSlasher.new(true) - await accountsInstance.initialize(registry.address) - await registry.setAddressFor(CeloContractName.Accounts, accountsInstance.address) - await registry.setAddressFor(CeloContractName.LockedGold, mockLockedGold.address) - await registry.setAddressFor(CeloContractName.Validators, validators.address) - await slasher.initialize(registry.address) - await mockLockedGold.setAccountTotalLockedGold(validator, 5000) - }) - - describe('#initialize()', () => { - it('should have set the owner', async () => { - const owner: string = await slasher.owner() - assert.equal(owner, accounts[0]) - }) - it('can only be called once', async () => { - await assertTransactionRevertWithReason( - slasher.initialize(registry.address), - 'contract already initialized' - ) - }) - }) - - describe('#approveSlashing()', () => { - it('should set slashable amount', async () => { - await slasher.approveSlashing(accounts[2], 1000) - const amount = await slasher.getApprovedSlashing(accounts[2]) - assert.equal(amount.toNumber(), 1000) - }) - it('should increment slashable amount when approved twice', async () => { - await slasher.approveSlashing(accounts[2], 1000) - await slasher.approveSlashing(accounts[2], 1000) - const amount = await slasher.getApprovedSlashing(accounts[2]) - assert.equal(amount.toNumber(), 2000) - }) - it('can only be called by owner', async () => { - await assertTransactionRevertWithReason( - slasher.approveSlashing(accounts[2], 1000, { from: nonOwner }), - 'Ownable: caller is not the owner' - ) - }) - }) - - describe('#slash()', () => { - it('fails if there is nothing to slash', async () => { - await assertTransactionRevertWithReason( - slasher.slash(validator, [], [], []), - 'No penalty given by governance' - ) - }) - it('decrements gold', async () => { - await slasher.approveSlashing(validator, 1000) - await slasher.slash(validator, [], [], []) - const amount = await mockLockedGold.accountTotalLockedGold(validator) - assert.equal(amount.toNumber(), 4000) - }) - it('has set the approved slashing to zero', async () => { - await slasher.approveSlashing(validator, 1000) - await slasher.slash(validator, [], [], []) - const amount = await slasher.getApprovedSlashing(validator) - assert.equal(amount.toNumber(), 0) - }) - it('should emit the corresponding event', async () => { - const amount = 1000 - await slasher.approveSlashing(validator, amount) - const resp = await slasher.slash(validator, [], [], []) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'GovernanceSlashPerformed', - args: { - account: validator, - amount: new BigNumber(amount), - }, - }) - }) - }) -}) diff --git a/packages/protocol/test/governance/validators/doublesigningslasher.ts b/packages/protocol/test/governance/validators/doublesigningslasher.ts deleted file mode 100644 index d7ad01eac..000000000 --- a/packages/protocol/test/governance/validators/doublesigningslasher.ts +++ /dev/null @@ -1,202 +0,0 @@ -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { - assertContainSubset, - assertTransactionRevertWithReason, -} from '@celo/protocol/lib/test-utils' -import BigNumber from 'bignumber.js' -import { - AccountsContract, - AccountsInstance, - DoubleSigningSlasherTestContract, - DoubleSigningSlasherTestInstance, - MockLockedGoldContract, - MockLockedGoldInstance, - MockValidatorsContract, - MockValidatorsInstance, - RegistryContract, - RegistryInstance, -} from 'types' - -const Accounts: AccountsContract = artifacts.require('Accounts') -const MockValidators: MockValidatorsContract = artifacts.require('MockValidators') -const DoubleSigningSlasher: DoubleSigningSlasherTestContract = artifacts.require( - 'DoubleSigningSlasherTest' -) -const MockLockedGold: MockLockedGoldContract = artifacts.require('MockLockedGold') -const Registry: RegistryContract = artifacts.require('Registry') - -// @ts-ignore -// TODO(mcortesi): Use BN -DoubleSigningSlasher.numberFormat = 'BigNumber' - -contract('DoubleSigningSlasher', (accounts: string[]) => { - let accountsInstance: AccountsInstance - let validators: MockValidatorsInstance - let registry: RegistryInstance - let mockLockedGold: MockLockedGoldInstance - let slasher: DoubleSigningSlasherTestInstance - - const nonOwner = accounts[1] - const validator = accounts[1] - const group = accounts[0] - - const slashingPenalty = 10000 - const slashingReward = 100 - - beforeEach(async () => { - accountsInstance = await Accounts.new(true) - await Promise.all(accounts.map((account) => accountsInstance.createAccount({ from: account }))) - mockLockedGold = await MockLockedGold.new() - registry = await Registry.new(true) - validators = await MockValidators.new() - slasher = await DoubleSigningSlasher.new() - await accountsInstance.initialize(registry.address) - await registry.setAddressFor(CeloContractName.Accounts, accountsInstance.address) - await registry.setAddressFor(CeloContractName.LockedGold, mockLockedGold.address) - await registry.setAddressFor(CeloContractName.Validators, validators.address) - await validators.affiliate(group, { from: validator }) - await validators.affiliate(accounts[3], { from: accounts[4] }) - await slasher.initialize(registry.address, slashingPenalty, slashingReward) - await Promise.all( - accounts.map((account) => mockLockedGold.setAccountTotalLockedGold(account, 50000)) - ) - }) - - describe('#initialize()', () => { - it('should have set the owner', async () => { - const owner: string = await slasher.owner() - assert.equal(owner, accounts[0]) - }) - it('should have set slashing incentives', async () => { - const res = await slasher.slashingIncentives() - assert.equal(res[0].toNumber(), 10000) - assert.equal(res[1].toNumber(), 100) - }) - it('can only be called once', async () => { - await assertTransactionRevertWithReason( - slasher.initialize(registry.address, 10000, 100), - 'contract already initialized' - ) - }) - }) - - describe('#setSlashingIncentives()', () => { - it('can only be set by the owner', async () => { - await assertTransactionRevertWithReason( - slasher.setSlashingIncentives(123, 67, { from: nonOwner }), - 'Ownable: caller is not the owner' - ) - }) - it('reward cannot be larger than penalty', async () => { - await assertTransactionRevertWithReason( - slasher.setSlashingIncentives(123, 678), - 'Penalty has to be larger than reward' - ) - }) - it('should have set slashing incentives', async () => { - await slasher.setSlashingIncentives(123, 67) - const res = await slasher.slashingIncentives() - assert.equal(res[0].toNumber(), 123) - assert.equal(res[1].toNumber(), 67) - }) - it('should emit the corresponding event', async () => { - const resp = await slasher.setSlashingIncentives(123, 67) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'SlashingIncentivesSet', - args: { - penalty: new BigNumber(123), - reward: new BigNumber(67), - }, - }) - }) - }) - - describe('#slash()', () => { - const blockNumber = 110 - const validatorIndex = 5 - const headerA = '0x121212' - const headerB = '0x131313' - const headerC = '0x111314' - beforeEach(async () => { - await slasher.setBlockNumber(headerA, blockNumber) - await slasher.setBlockNumber(headerB, blockNumber + 1) - await slasher.setBlockNumber(headerC, blockNumber) - const epoch = (await slasher.getEpochNumberOfBlock(blockNumber)).toNumber() - await slasher.setEpochSigner(epoch, validatorIndex, validator) - await slasher.setEpochSigner(epoch, validatorIndex + 1, accounts[4]) - // Signed by validators 0 to 5 - const bitmap = '0x000000000000000000000000000000000000000000000000000000000000003f' - await slasher.setNumberValidators(7) - await slasher.setVerifiedSealBitmap(headerA, bitmap) - await slasher.setVerifiedSealBitmap(headerB, bitmap) - await slasher.setVerifiedSealBitmap(headerC, bitmap) - }) - it('fails if block numbers do not match', async () => { - await assertTransactionRevertWithReason( - slasher.slash(validator, validatorIndex, headerA, headerB, 0, [], [], [], [], [], []), - 'Block headers are from different height' - ) - }) - it('fails if is not signed at index', async () => { - await assertTransactionRevertWithReason( - slasher.slash(accounts[4], validatorIndex + 1, headerA, headerC, 0, [], [], [], [], [], []), - "Didn't sign first block" - ) - }) - it('fails if epoch signer is wrong', async () => { - await assertTransactionRevertWithReason( - slasher.slash(accounts[4], validatorIndex, headerA, headerC, 0, [], [], [], [], [], []), - "Wasn't a signer with given index" - ) - }) - it('fails if there are not enough signers', async () => { - await slasher.setNumberValidators(100) - await assertTransactionRevertWithReason( - slasher.slash(validator, validatorIndex, headerA, headerC, 0, [], [], [], [], [], []), - 'Not enough signers in the first block' - ) - }) - it('should emit the corresponding event', async () => { - const resp = await slasher.slash( - validator, - validatorIndex, - headerA, - headerC, - 0, - [], - [], - [], - [], - [], - [] - ) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'DoubleSigningSlashPerformed', - args: { - validator, - blockNumber: new BigNumber(blockNumber), - }, - }) - }) - it('decrements gold when success', async () => { - await slasher.slash(validator, validatorIndex, headerA, headerC, 0, [], [], [], [], [], []) - const balance = await mockLockedGold.accountTotalLockedGold(validator) - assert.equal(balance.toNumber(), 40000) - }) - it('also slashes group', async () => { - await slasher.slash(validator, validatorIndex, headerA, headerC, 0, [], [], [], [], [], []) - const balance = await mockLockedGold.accountTotalLockedGold(group) - assert.equal(balance.toNumber(), 40000) - }) - it('fails when tried second time', async () => { - await slasher.slash(validator, validatorIndex, headerA, headerC, 0, [], [], [], [], [], []) - await assertTransactionRevertWithReason( - slasher.slash(validator, validatorIndex, headerA, headerC, 0, [], [], [], [], [], []), - ' Already slashed' - ) - }) - }) -}) diff --git a/packages/protocol/test/governance/validators/downtimeslasher.ts b/packages/protocol/test/governance/validators/downtimeslasher.ts deleted file mode 100644 index a7319efcc..000000000 --- a/packages/protocol/test/governance/validators/downtimeslasher.ts +++ /dev/null @@ -1,885 +0,0 @@ -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { - assertLogMatches2, - assertRevert, - assertTransactionRevertWithReason, - getEpochNumberOfBlock, - getFirstBlockNumberForEpoch, - jsonRpc, -} from '@celo/protocol/lib/test-utils' -import { - AccountsContract, - AccountsInstance, - DowntimeSlasherTestContract, - DowntimeSlasherTestInstance, - MockLockedGoldContract, - MockLockedGoldInstance, - MockValidatorsContract, - MockValidatorsInstance, - RegistryContract, - RegistryInstance, -} from 'types' - -const Accounts: AccountsContract = artifacts.require('Accounts') -const MockValidators: MockValidatorsContract = artifacts.require('MockValidators') -const DowntimeSlasher: DowntimeSlasherTestContract = artifacts.require('DowntimeSlasherTest') -const MockLockedGold: MockLockedGoldContract = artifacts.require('MockLockedGold') -const Registry: RegistryContract = artifacts.require('Registry') - -// @ts-ignore -// TODO(mcortesi): Use BN -DowntimeSlasher.numberFormat = 'BigNumber' - -contract('DowntimeSlasher', (accounts: string[]) => { - let accountsInstance: AccountsInstance - let validators: MockValidatorsInstance - let registry: RegistryInstance - let mockLockedGold: MockLockedGoldInstance - let slasher: DowntimeSlasherTestInstance - let epochSize: number - - const nonOwner = accounts[1] - const validatorList = [accounts[2], accounts[3], accounts[4]] - const groups = [accounts[0], accounts[1]] - - const slashingPenalty = 10000 - const slashingReward = 100 - const slashableDowntime = 12 - const intervalSize = 4 - - async function presetParentSealForBlocks( - fromBlock: number, - numberOfBlocks: number, - bitmaps: string[] - ) { - const startEpoch = getEpochNumberOfBlock(fromBlock, epochSize) - const nextEpochStart = getFirstBlockNumberForEpoch(startEpoch + 1, epochSize) - for (let i = fromBlock; i < fromBlock + numberOfBlocks; i++) { - await slasher.setParentSealBitmap(i + 1, i < nextEpochStart ? bitmaps[0] : bitmaps[1]) - } - } - - async function calculateEverySlot( - startBlock: number - ): Promise<{ startBlocks: number[]; endBlocks: number[] }> { - const startBlocks: number[] = [] - const endBlocks: number[] = [] - const actualSlashableDowntime = (await slasher.slashableDowntime()).toNumber() - - const startEpoch = getEpochNumberOfBlock(startBlock, epochSize) - const nextEpochStart = getFirstBlockNumberForEpoch(startEpoch, epochSize) - const endBlock = startBlock + actualSlashableDowntime - 1 - for (let i = startBlock; i <= endBlock; ) { - let endBlockForSlot = i + intervalSize - 1 - endBlockForSlot = endBlockForSlot > endBlock ? endBlock : endBlockForSlot - - // Avoids crossing the epoch - endBlockForSlot = - endBlockForSlot >= nextEpochStart && i < nextEpochStart - ? nextEpochStart - 1 - : endBlockForSlot - startBlocks.push(i) - endBlocks.push(endBlockForSlot) - await slasher.setBitmapForInterval(i, endBlockForSlot) - i = endBlockForSlot + 1 - } - - return { startBlocks, endBlocks } - } - - async function generateProofs(startBlocks: number[], endBlocks: number[]) { - for (let i = 0; i < startBlocks.length; i += 1) { - await slasher.setBitmapForInterval(startBlocks[i], endBlocks[i]) - } - } - - beforeEach(async () => { - accountsInstance = await Accounts.new(true) - await Promise.all(accounts.map((account) => accountsInstance.createAccount({ from: account }))) - mockLockedGold = await MockLockedGold.new() - registry = await Registry.new(true) - validators = await MockValidators.new() - slasher = await DowntimeSlasher.new() - epochSize = (await slasher.getEpochSize()).toNumber() - await accountsInstance.initialize(registry.address) - await registry.setAddressFor(CeloContractName.Accounts, accountsInstance.address) - await registry.setAddressFor(CeloContractName.LockedGold, mockLockedGold.address) - await registry.setAddressFor(CeloContractName.Validators, validators.address) - await validators.affiliate(groups[0], { from: validatorList[0] }) - await validators.affiliate(groups[0], { from: validatorList[1] }) - await validators.affiliate(groups[1], { from: validatorList[2] }) - await slasher.initialize(registry.address, slashingPenalty, slashingReward, slashableDowntime) - for (const account of accounts) { - await mockLockedGold.setAccountTotalLockedGold(account, 50000) - } - }) - - describe('#initialize()', () => { - it('should have set the owner', async () => { - const owner: string = await slasher.owner() - assert.equal(owner, accounts[0]) - }) - - it('should have set slashing incentives', async () => { - const res = await slasher.slashingIncentives() - assert.equal(res[0].toNumber(), 10000) - assert.equal(res[1].toNumber(), 100) - }) - - it('should have set slashable downtime', async () => { - const res = await slasher.slashableDowntime() - assert.equal(res.toNumber(), slashableDowntime) - }) - - it('can only be called once', async () => { - await assertTransactionRevertWithReason( - slasher.initialize(registry.address, 10000, 100, 2), - 'contract already initialized' - ) - }) - }) - - describe('#setSlashingIncentives()', () => { - it('can only be set by the owner', async () => { - await assertTransactionRevertWithReason( - slasher.setSlashingIncentives(123, 67, { from: nonOwner }), - 'Ownable: caller is not the owner' - ) - }) - - it('should have set slashing incentives', async () => { - await slasher.setSlashingIncentives(123, 67) - const res = await slasher.slashingIncentives() - assert.equal(res[0].toNumber(), 123) - assert.equal(res[1].toNumber(), 67) - }) - - it('reward cannot be larger than penalty', async () => { - await assertTransactionRevertWithReason( - slasher.setSlashingIncentives(123, 678), - 'Penalty has to be larger than reward' - ) - }) - - it('should emit the SlashingIncentivesSet corresponding event', async () => { - const resp = await slasher.setSlashingIncentives(123, 67) - assert.equal(resp.logs.length, 1) - assertLogMatches2(resp.logs[0], { - event: 'SlashingIncentivesSet', - args: { - penalty: 123, - reward: 67, - }, - }) - }) - }) - - describe('#setSlashableDowntime()', () => { - it('can only be set by the owner', async () => { - await assertTransactionRevertWithReason( - slasher.setSlashableDowntime(23, { from: nonOwner }), - ' Ownable: caller is not the owner' - ) - }) - - it('should have set slashable downtime', async () => { - await slasher.setSlashableDowntime(23) - const res = await slasher.slashableDowntime() - assert.equal(res.toNumber(), 23) - }) - - it('should emit the SlashableDowntimeSet corresponding event', async () => { - const resp = await slasher.setSlashableDowntime(23) - assert.equal(resp.logs.length, 1) - assertLogMatches2(resp.logs[0], { - event: 'SlashableDowntimeSet', - args: { - interval: 23, - }, - }) - }) - }) - - describe('#getBitmapForInterval()', () => { - let blockNumber: number - let epoch: number - - beforeEach(async () => { - await slasher.setNumberValidators(2) - blockNumber = await web3.eth.getBlockNumber() - epoch = getEpochNumberOfBlock(blockNumber, epochSize) - await slasher.setEpochSigner(epoch, 0, validatorList[0]) - }) - - it('fails if endBlock < startBlock', async () => { - await assertRevert( - slasher.getBitmapForInterval(2, 3), - 'endBlock must be greater or equal than startBlock' - ) - }) - - it('fails if the currentBlock is part of the interval', async () => { - const currentBlock = await web3.eth.getBlockNumber() - await assertRevert( - slasher.getBitmapForInterval(currentBlock, currentBlock), - 'the signature bitmap for endBlock is not yet available' - ) - }) - - it('fails if startBlock is older than 4 epochs', async () => { - // we make sure that 4 epochs passed - do { - blockNumber = await web3.eth.getBlockNumber() - await jsonRpc(web3, 'evm_mine', []) - } while (blockNumber < epochSize * 4 + 2) - blockNumber = blockNumber - epochSize * 4 - await assertRevert( - slasher.getBitmapForInterval(blockNumber, blockNumber), - 'startBlock must be within 4 epochs of the current head' - ) - }) - - it('fails if startBlock and endBlock are not from the same epoch', async () => { - blockNumber = blockNumber - 2 - await assertRevert( - slasher.getBitmapForInterval(blockNumber - epochSize, blockNumber), - 'startBlock and endBlock must be in the same epoch' - ) - }) - - it('fails if startBlock and endBlock are not from the same epoch', async () => { - blockNumber = blockNumber - 2 - await assertRevert( - slasher.getBitmapForInterval(blockNumber - epochSize, blockNumber), - 'startBlock and endBlock must be in the same epoch' - ) - }) - }) - - describe('#setBitmapForInterval()', () => { - let blockNumber: number - let epoch: number - - beforeEach(async () => { - await slasher.setNumberValidators(2) - blockNumber = await web3.eth.getBlockNumber() - // To ensure blockNumber with valid parentSealBitmap - blockNumber = blockNumber - 3 - // This ensures 2 consecutive blocks in the same epoch - blockNumber = blockNumber % epochSize === 0 ? blockNumber - 1 : blockNumber - epoch = getEpochNumberOfBlock(blockNumber, epochSize) - await slasher.setEpochSigner(epoch, 0, validatorList[0]) - await slasher.setParentSealBitmap( - blockNumber + 1, - '0x0000000000000000000000000000000000000000000000000000000000000001' - ) - await slasher.setParentSealBitmap( - blockNumber + 2, - '0x0000000000000000000000000000000000000000000000000000000000000002' - ) - }) - - it('fails if the interval was already set', async () => { - const resp = await slasher.setBitmapForInterval(blockNumber, blockNumber + 1) - assert.equal(resp.logs.length, 1) - - await assertTransactionRevertWithReason( - slasher.setBitmapForInterval(blockNumber, blockNumber + 1), - 'bitmap already set' - ) - }) - - it('should emit the BitmapSetForInterval corresponding event', async () => { - const resp = await slasher.setBitmapForInterval(blockNumber, blockNumber + 1) - assert.equal(resp.logs.length, 1) - assertLogMatches2(resp.logs[0], { - event: 'BitmapSetForInterval', - args: { - sender: accounts[0], - startBlock: blockNumber, - endBlock: blockNumber + 1, - bitmap: '0x0000000000000000000000000000000000000000000000000000000000000003', - }, - }) - }) - }) - - describe('#slash()', () => { - let epoch: number - - // Signed by validators 0 and 1 - const bitmapVI01 = '0x0000000000000000000000000000000000000000000000000000000000000003' - // Signed by validator 1 - const bitmapVI1 = '0x0000000000000000000000000000000000000000000000000000000000000002' - // Signed by validator 0 - const bitmapVI0 = '0x0000000000000000000000000000000000000000000000000000000000000001' - // Signed by validator 99 - const bitmapVI99 = '0x0000000000000000000000000000000000000008000000000000000000000000' - const validatorIndexInEpoch: number = 0 - const bitmapWithoutValidator: string[] = [bitmapVI1, bitmapVI0] - - async function ensureValidatorIsSlashable( - startBlock: number, - validatorIndices: number[] - ): Promise<{ startBlocks: number[]; endBlocks: number[] }> { - const bitmapMasks = validatorIndices.map((vi) => bitmapWithoutValidator[vi]) - await presetParentSealForBlocks(startBlock, slashableDowntime, bitmapMasks) - // Signs the outer limits to be 100% secure that the boundaries are well tested - await presetParentSealForBlocks(startBlock - 1, 1, [bitmapVI01]) - await presetParentSealForBlocks(startBlock + slashableDowntime, 1, [bitmapVI01]) - - return calculateEverySlot(startBlock) - } - - // This function will wait until the middle of a new epoch is reached. - // We consider blocks are "safe" if the test could perform a slash, without - // the context of the other tests. - // This property ensures that each test has an epoch to work with (not depends - // on previous tests), and there are enough blocks on that epoch to have a validator - // down for a possible slash. - async function waitUntilSafeBlocks(safeEpoch: number) { - let blockNumber: number = 0 - const blockStableBetweenTests = getFirstBlockNumberForEpoch(safeEpoch, epochSize) - 1 - do { - blockNumber = await web3.eth.getBlockNumber() - await jsonRpc(web3, 'evm_mine', []) - } while ( - blockNumber < blockStableBetweenTests || - // Middle of the epoch - blockNumber % epochSize <= epochSize * 0.5 - ) - } - - before(async () => { - const blockNumber: number = await web3.eth.getBlockNumber() - epoch = getEpochNumberOfBlock(blockNumber, epochSize) - }) - - beforeEach(async () => { - await waitUntilSafeBlocks(epoch) - await slasher.setNumberValidators(2) - }) - - afterEach(async () => { - const blockNumber: number = await web3.eth.getBlockNumber() - const newEpoch = getEpochNumberOfBlock(blockNumber, epochSize) - - // Optimization to make the testing batch run faster. - // This "recovers" a gap of more that 1 epoch, and avoids waiting more than an epoch - // between tests. - if (newEpoch === epoch) { - epoch += 1 - } else { - epoch = newEpoch - } - }) - - describe('slashable interval in the same epoch', async () => { - beforeEach(async () => { - await slasher.setEpochSigner(epoch, validatorIndexInEpoch, validatorList[0]) - }) - - // Test boundaries - it('fails if the first block was signed', async () => { - const startBlock = getFirstBlockNumberForEpoch(epoch, epochSize) - - // Set the parentSeal bitmaps for every block without the validator's signature - await presetParentSealForBlocks(startBlock + 1, slashableDowntime - 1, [ - bitmapWithoutValidator[validatorIndexInEpoch], - ]) - - // First block with every validator signatures - await presetParentSealForBlocks(startBlock, 1, [bitmapVI01]) - const slotArrays = await calculateEverySlot(startBlock) - await assertTransactionRevertWithReason( - slasher.slash( - slotArrays.startBlocks, - slotArrays.endBlocks, - [validatorIndexInEpoch], - 0, - [], - [], - [], - [], - [], - [] - ), - 'not down' - ) - }) - - it('fails if the last block was signed', async () => { - const startBlock = getFirstBlockNumberForEpoch(epoch, epochSize) - - // Set the parentSeal bitmaps for every block without the validator's signature - await presetParentSealForBlocks(startBlock, slashableDowntime - 1, [ - bitmapWithoutValidator[validatorIndexInEpoch], - ]) - - // Last block with every validator signatures - await presetParentSealForBlocks(startBlock + slashableDowntime - 1, 1, [bitmapVI01]) - const slotArrays = await calculateEverySlot(startBlock) - await assertTransactionRevertWithReason( - slasher.slash( - slotArrays.startBlocks, - slotArrays.endBlocks, - [validatorIndexInEpoch], - 0, - [], - [], - [], - [], - [], - [] - ), - 'not down' - ) - }) - - it('fails if one block in the middle was signed', async () => { - const startBlock = getFirstBlockNumberForEpoch(epoch, epochSize) - - // Set the parentSeal bitmaps for every block without the validator's signature - await presetParentSealForBlocks(startBlock, slashableDowntime, [ - bitmapWithoutValidator[validatorIndexInEpoch], - ]) - - // Middle block with every validator signatures - await presetParentSealForBlocks(startBlock + intervalSize, 1, [bitmapVI01]) - const slotArrays = await calculateEverySlot(startBlock) - await assertTransactionRevertWithReason( - slasher.slash( - slotArrays.startBlocks, - slotArrays.endBlocks, - [validatorIndexInEpoch], - 0, - [], - [], - [], - [], - [], - [] - ), - 'not down' - ) - }) - - it('fails if the first block was signed using a big index', async () => { - await slasher.setNumberValidators(100) - await slasher.setEpochSigner(epoch, 99, validatorList[2]) - const startBlock = getFirstBlockNumberForEpoch(epoch, epochSize) - - // Set the parentSeal bitmaps for every block without the validator's signature - await presetParentSealForBlocks(startBlock + 1, slashableDowntime - 1, [bitmapVI0]) - - // First block with every validator signatures - await presetParentSealForBlocks(startBlock, 1, [bitmapVI99]) - const slotArrays = await calculateEverySlot(startBlock) - await assertTransactionRevertWithReason( - slasher.slash( - slotArrays.startBlocks, - slotArrays.endBlocks, - [99], - 0, - [], - [], - [], - [], - [], - [] - ), - 'not down' - ) - }) - - describe('when the validator was down', () => { - let startBlock: number - - beforeEach(async () => { - startBlock = getFirstBlockNumberForEpoch(epoch, epochSize) - await presetParentSealForBlocks(startBlock, slashableDowntime, [ - bitmapWithoutValidator[validatorIndexInEpoch], - ]) - }) - - describe('when the intervals cover the SlashableDowntime window', () => { - it('succeeds if intervals overlap', async () => { - const startBlocks = [startBlock, startBlock + 2] - const endBlocks = [ - startBlock + slashableDowntime - 3, - startBlock + slashableDowntime - 1, - ] - await generateProofs(startBlocks, endBlocks) - await slasher.slash( - startBlocks, - endBlocks, - [validatorIndexInEpoch], - 0, - [], - [], - [], - [], - [], - [] - ) - const balance = await mockLockedGold.accountTotalLockedGold(validatorList[0]) - assert.equal(balance.toNumber(), 40000) - }) - - it('succeeds if intervals cover more than the SlashableDowntime window', async () => { - const startBlocks = [startBlock, startBlock + intervalSize] - const endBlocks = [startBlock + intervalSize - 1, startBlock + slashableDowntime + 3] - - for (let i = 0; i < startBlocks.length; i += 1) { - await presetParentSealForBlocks(startBlocks[i], endBlocks[i] - startBlocks[i] + 1, [ - bitmapWithoutValidator[validatorIndexInEpoch], - ]) - } - await generateProofs(startBlocks, endBlocks) - await slasher.slash( - startBlocks, - endBlocks, - [validatorIndexInEpoch], - 0, - [], - [], - [], - [], - [], - [] - ) - const balance = await mockLockedGold.accountTotalLockedGold(validatorList[0]) - assert.equal(balance.toNumber(), 40000) - }) - - it('fails if intervals are not contiguous', async () => { - // The slashableDowntime is covered with interval(0) and interval(2), but - // interval(1) breaks the interval contiguity. - const startBlocks = [ - startBlock, - startBlock + intervalSize * 2, - startBlock + intervalSize, - ] - const endBlocks = [ - startBlocks[0] + intervalSize - 1, - startBlocks[1] + intervalSize - 1, - startBlock + slashableDowntime - 1, - ] - - for (let i = 0; i < startBlocks.length; i += 1) { - await presetParentSealForBlocks(startBlocks[i], endBlocks[i] - startBlocks[i] + 1, [ - bitmapWithoutValidator[validatorIndexInEpoch], - ]) - } - await generateProofs(startBlocks, endBlocks) - await assertTransactionRevertWithReason( - slasher.slash( - startBlocks, - endBlocks, - [validatorIndexInEpoch], - 0, - [], - [], - [], - [], - [], - [] - ), - 'each interval must start at most one block after the end of the previous interval' - ) - }) - }) - - it("fails if the intervals don't cover the SlashableDowntime window", async () => { - const startBlocks = [startBlock, startBlock + intervalSize] - const endBlocks = [ - startBlocks[0] + intervalSize - 1, - startBlocks[1] + intervalSize - 1, - startBlock + slashableDowntime - 1, - ] - for (let i = 0; i < startBlocks.length; i += 1) { - await presetParentSealForBlocks(startBlocks[i], endBlocks[i] - startBlocks[i] + 1, [ - bitmapWithoutValidator[validatorIndexInEpoch], - ]) - } - await generateProofs(startBlocks, endBlocks) - await assertTransactionRevertWithReason( - slasher.slash( - startBlocks, - endBlocks, - [validatorIndexInEpoch], - 0, - [], - [], - [], - [], - [], - [] - ), - 'startBlocks and endBlocks must have the same length' - ) - }) - }) - - describe('when slashing succeeds', () => { - let resp: Truffle.TransactionResponse - let startBlock: number - let endBlock: number - - beforeEach(async () => { - startBlock = getFirstBlockNumberForEpoch(epoch, epochSize) - const slotArrays = await ensureValidatorIsSlashable(startBlock, [validatorIndexInEpoch]) - endBlock = slotArrays.endBlocks[slotArrays.endBlocks.length - 1] - resp = await slasher.slash( - slotArrays.startBlocks, - slotArrays.endBlocks, - [validatorIndexInEpoch], - 0, - [], - [], - [], - [], - [], - [] - ) - }) - - it('should emit the DowntimeSlashPerformed corresponding event', async () => { - assertLogMatches2(resp.logs[0], { - event: 'DowntimeSlashPerformed', - args: { - validator: validatorList[0], - startBlock, - endBlock, - }, - }) - }) - - it('decrements gold', async () => { - const balance = await mockLockedGold.accountTotalLockedGold(validatorList[0]) - assert.equal(balance.toNumber(), 40000) - }) - - it('also slashes group', async () => { - const balance = await mockLockedGold.accountTotalLockedGold(groups[0]) - assert.equal(balance.toNumber(), 40000) - }) - - it('can be slashed twice in the same epoch', async () => { - // Just to make sure that the validator was slashed - let balance = await mockLockedGold.accountTotalLockedGold(validatorList[0]) - assert.equal(balance.toNumber(), 40000) - const newStartBlock = startBlock + slashableDowntime * 2 - const slotArrays = await ensureValidatorIsSlashable(newStartBlock, [ - validatorIndexInEpoch, - validatorIndexInEpoch, - ]) - await slasher.slash( - slotArrays.startBlocks, - slotArrays.endBlocks, - [validatorIndexInEpoch], - 0, - [], - [], - [], - [], - [], - [] - ) - balance = await mockLockedGold.accountTotalLockedGold(validatorList[0]) - assert.equal(balance.toNumber(), 30000) - }) - }) - }) - - describe('slashable interval crossing epochs', async () => { - let startBlock: number - - // Wait another epoch, to avoid "same epoch slashes" restriction - beforeEach(async () => { - epoch = epoch + 1 - await waitUntilSafeBlocks(epoch) - await slasher.setEpochSigner(epoch, validatorIndexInEpoch, validatorList[0]) - startBlock = getFirstBlockNumberForEpoch(epoch, epochSize) - intervalSize - await slasher.setEpochSigner(epoch, validatorIndexInEpoch, validatorList[0]) - }) - - describe('when the last block was signed', () => { - it("fails if it didn't switched indices", async () => { - await slasher.setEpochSigner(epoch - 1, validatorIndexInEpoch, validatorList[0]) - // Set the parentSeal bitmaps for every block without the validator's signature - await presetParentSealForBlocks(startBlock, slashableDowntime - 1, [ - bitmapWithoutValidator[validatorIndexInEpoch], - bitmapWithoutValidator[validatorIndexInEpoch], - ]) - // Last block with every validator signatures - await presetParentSealForBlocks(startBlock + slashableDowntime - 1, 1, [bitmapVI01]) - const slotArrays = await calculateEverySlot(startBlock) - await assertTransactionRevertWithReason( - slasher.slash( - slotArrays.startBlocks, - slotArrays.endBlocks, - [validatorIndexInEpoch, validatorIndexInEpoch], - 0, - [], - [], - [], - [], - [], - [] - ), - 'not down' - ) - }) - - it('fails if it switched indices', async () => { - await slasher.setEpochSigner(epoch - 1, 1, validatorList[0]) - - // All the blocks, changes the bitmap in the middle - await presetParentSealForBlocks(startBlock, slashableDowntime - 1, [ - bitmapWithoutValidator[1], - bitmapWithoutValidator[validatorIndexInEpoch], - ]) - - // Last block with every validator signatures - await presetParentSealForBlocks(startBlock + slashableDowntime - 1, 1, [bitmapVI01]) - const slotArrays = await calculateEverySlot(startBlock) - await assertTransactionRevertWithReason( - slasher.slash( - slotArrays.startBlocks, - slotArrays.endBlocks, - [1, validatorIndexInEpoch], - 0, - [], - [], - [], - [], - [], - [] - ), - 'not down' - ) - }) - }) - - describe('when the validator was down', () => { - it('succeeds with validator index change', async () => { - await slasher.setEpochSigner(epoch - 1, 1, validatorList[0]) - const slotArrays = await ensureValidatorIsSlashable(startBlock, [ - 1, - validatorIndexInEpoch, - ]) - await slasher.slash( - slotArrays.startBlocks, - slotArrays.endBlocks, - [1, validatorIndexInEpoch], - 0, - [], - [], - [], - [], - [], - [] - ) - const balance = await mockLockedGold.accountTotalLockedGold(validatorList[0]) - assert.equal(balance.toNumber(), 40000) - }) - - it('succeeds without validator index change', async () => { - await slasher.setEpochSigner(epoch - 1, validatorIndexInEpoch, validatorList[0]) - const slotArrays = await ensureValidatorIsSlashable(startBlock, [ - validatorIndexInEpoch, - validatorIndexInEpoch, - ]) - - await slasher.slash( - slotArrays.startBlocks, - slotArrays.endBlocks, - [validatorIndexInEpoch, validatorIndexInEpoch], - 0, - [], - [], - [], - [], - [], - [] - ) - const balance = await mockLockedGold.accountTotalLockedGold(validatorList[0]) - assert.equal(balance.toNumber(), 40000) - }) - - it("fails if the indices don't match the same validator", async () => { - await slasher.setEpochSigner(epoch - 1, 1, validatorList[0]) - await slasher.setEpochSigner(epoch, 1, validatorList[1]) - const slotArrays = await ensureValidatorIsSlashable(startBlock, [ - 1, - validatorIndexInEpoch, - ]) - await assertTransactionRevertWithReason( - slasher.slash( - slotArrays.startBlocks, - slotArrays.endBlocks, - [1, 1], - 0, - [], - [], - [], - [], - [], - [] - ), - 'indices do not point to the same validator' - ) - }) - }) - - describe('when slashing succeeds', () => { - beforeEach(async () => { - await slasher.setEpochSigner(epoch - 1, validatorIndexInEpoch, validatorList[0]) - const slotArrays = await ensureValidatorIsSlashable(startBlock, [ - validatorIndexInEpoch, - validatorIndexInEpoch, - ]) - await slasher.slash( - slotArrays.startBlocks, - slotArrays.endBlocks, - [validatorIndexInEpoch, validatorIndexInEpoch], - 0, - [], - [], - [], - [], - [], - [] - ) - }) - - it('cannot be slashed if the validator has a newer slash', async () => { - const newStartBlock = getFirstBlockNumberForEpoch(epoch - 1, epochSize) + 1 - - // Just to make sure that it was slashed - const balance = await mockLockedGold.accountTotalLockedGold(validatorList[0]) - assert.equal(balance.toNumber(), 40000) - const slotArrays = await ensureValidatorIsSlashable(newStartBlock, [ - validatorIndexInEpoch, - ]) - await assertTransactionRevertWithReason( - slasher.slash( - slotArrays.startBlocks, - slotArrays.endBlocks, - [validatorIndexInEpoch], - 0, - [], - [], - [], - [], - [], - [] - ), - 'cannot slash validator for downtime for which they may already have been slashed' - ) - }) - }) - }) - }) -}) diff --git a/packages/protocol/test/governance/validators/sortedlinkedlist.ts b/packages/protocol/test/governance/validators/sortedlinkedlist.ts deleted file mode 100644 index 2f1b8dffa..000000000 --- a/packages/protocol/test/governance/validators/sortedlinkedlist.ts +++ /dev/null @@ -1,411 +0,0 @@ -import { assertTransactionRevertWithReason } from '@celo/protocol/lib/test-utils' -import BigNumber from 'bignumber.js' -import { IntegerSortedLinkedListTestContract, IntegerSortedLinkedListTestInstance } from 'types' - -const IntegerSortedLinkedListTest: IntegerSortedLinkedListTestContract = artifacts.require( - 'IntegerSortedLinkedListTest' -) - -// @ts-ignore -// TODO(mcortesi): Use BN.js -IntegerSortedLinkedListTest.numberFormat = 'BigNumber' - -// TODO(asaj): Test SoredLinkedList rather than IntegerSortedLinkedList -contract('IntegerSortedLinkedListTest', () => { - let sortedListTest: IntegerSortedLinkedListTestInstance - beforeEach(async () => { - sortedListTest = await IntegerSortedLinkedListTest.new() - }) - - describe('#insert()', () => { - const key = 1 - const value = 5 - it('should add a single element to the list', async () => { - await sortedListTest.insert(key, value, 0, 0) - assert.isTrue(await sortedListTest.contains(key)) - const [keys, values] = await sortedListTest.getElements() - assert.equal(keys.length, 1) - assert.equal(values.length, 1) - assert.equal(keys[0].toNumber(), key) - assert.equal(values[0].toNumber(), value) - }) - - it('should increment numElements', async () => { - await sortedListTest.insert(key, value, 0, 0) - assert.equal((await sortedListTest.getNumElements()).toNumber(), 1) - }) - - it('should update the head', async () => { - await sortedListTest.insert(key, value, 0, 0) - assert.equal((await sortedListTest.head()).toNumber(), key) - }) - - it('should update the tail', async () => { - await sortedListTest.insert(key, value, 0, 0) - assert.equal((await sortedListTest.tail()).toNumber(), key) - }) - - it('should revert if key is 0', async () => { - await assertTransactionRevertWithReason(sortedListTest.insert(0, value, 0, 0), 'invalid key') - }) - - it('should revert if lesser is equal to key', async () => { - await assertTransactionRevertWithReason( - sortedListTest.insert(key, value, key, 0), - 'invalid key' - ) - }) - - it('should revert if greater is equal to key', async () => { - await assertTransactionRevertWithReason( - sortedListTest.insert(key, value, 0, key), - 'invalid key' - ) - }) - - describe('when an element is already in the list', () => { - beforeEach(async () => { - await sortedListTest.insert(key, value, 0, 0) - }) - - it('should revert when inserting an element already in the list', async () => { - await assertTransactionRevertWithReason( - sortedListTest.insert(key, value, 0, key), - 'invalid key' - ) - }) - - it('should revert when inserting a non-maximal element at the head of the list', async () => { - const nonKey = key - 1 - const newKey = key + 1 - await assertTransactionRevertWithReason( - sortedListTest.insert(newKey, value - 1, nonKey, 0), - 'greater and lesser key zero' - ) - }) - }) - }) - - describe('#update()', () => { - const key = 1 - const value = 10 - const newValue = 20 - beforeEach(async () => { - await sortedListTest.insert(key, value, 0, 0) - }) - - it('should update the value for an existing element', async () => { - await sortedListTest.update(key, newValue, 0, 0) - assert.isTrue(await sortedListTest.contains(key)) - const [keys, values] = await sortedListTest.getElements() - assert.equal(keys.length, 1) - assert.equal(values.length, 1) - assert.equal(keys[0].toNumber(), key) - assert.equal(values[0].toNumber(), newValue) - }) - - it('should revert if the key is not in the list', async () => { - await assertTransactionRevertWithReason( - sortedListTest.update(key + 1, newValue, 0, 0), - 'key not in list' - ) - }) - - it('should revert if lesser is equal to key', async () => { - await assertTransactionRevertWithReason( - sortedListTest.update(key, newValue, key, 0), - 'invalid key' - ) - }) - - it('should revert if greater is equal to key', async () => { - await assertTransactionRevertWithReason( - sortedListTest.update(key, newValue, 0, key), - 'invalid key' - ) - }) - }) - - describe('#remove()', () => { - const key = 1 - const value = 10 - beforeEach(async () => { - await sortedListTest.insert(key, value, 0, 0) - }) - - it('should remove the element from the list', async () => { - await sortedListTest.remove(key) - assert.isFalse(await sortedListTest.contains(key)) - const [keys, values] = await sortedListTest.getElements() - assert.equal(keys.length, 0) - assert.equal(values.length, 0) - }) - - it('should decrement numElements', async () => { - await sortedListTest.remove(key) - assert.equal((await sortedListTest.getNumElements()).toNumber(), 0) - }) - - it('should update the head', async () => { - await sortedListTest.remove(key) - assert.equal((await sortedListTest.head()).toNumber(), 0) - }) - - it('should update the tail', async () => { - await sortedListTest.remove(key) - assert.equal((await sortedListTest.tail()).toNumber(), 0) - }) - - it('should revert if the key is not in the list', async () => { - await assertTransactionRevertWithReason(sortedListTest.remove(key + 1), 'key not in list') - }) - }) - - describe('#popN()', () => { - const n = 3 - const numElements = 10 - beforeEach(async () => { - for (let key = 1; key < numElements + 1; key++) { - const value = key * 10 - await sortedListTest.insert(key, value, key - 1, 0) - } - }) - - it('should remove the n keys with the largest values', async () => { - await sortedListTest.popN(n) - for (let key = 1; key < numElements + 1; key++) { - if (key <= numElements - n) { - assert.isTrue(await sortedListTest.contains(key)) - } else { - assert.isFalse(await sortedListTest.contains(key)) - } - } - const [keys, values] = await sortedListTest.getElements() - assert.equal(keys.length, numElements - n) - assert.equal(values.length, numElements - n) - }) - - it('should return the n keys with the largest values', async () => { - const popped = await sortedListTest.popN.call(n) - const expectedPopped = Array.from(Array(numElements + 1).keys()) - .filter((x) => x > numElements - n) - .reverse() - assert.deepEqual( - popped.map((x) => x.toNumber()), - expectedPopped - ) - }) - - it('should decrement numElements', async () => { - await sortedListTest.popN(n) - assert.equal((await sortedListTest.getNumElements()).toNumber(), numElements - n) - }) - - it('should update the head', async () => { - await sortedListTest.popN(n) - assert.equal((await sortedListTest.head()).toNumber(), numElements - n) - }) - - it('should revert if n is greater than the number of elements', async () => { - await assertTransactionRevertWithReason( - sortedListTest.popN(numElements + 1), - 'not enough elements' - ) - }) - }) - - describe('when there are multiple inserts, updates, and removals', () => { - interface SortedElement { - key: BigNumber - value: BigNumber - } - - enum SortedLinkedListActionType { - Update = 1, - Remove, - Insert, - } - - interface SortedLinkedListAction { - actionType: SortedLinkedListActionType - element: SortedElement - } - - const randomElement = (list: any[]) => { - return list[Math.floor(BigNumber.random().times(list.length).toNumber())] - } - - const makeActionSequence = (length: number, numKeys: number): SortedLinkedListAction[] => { - const sequence = [] - const listKeys = new Set([]) - for (let i = 0; i < length; i++) { - const keyOptions = Array.from({ length: numKeys }, (_, j) => new BigNumber(j + 1)) - const key = randomElement(keyOptions) - let action - if (listKeys.has(key.toNumber())) { - action = randomElement([ - SortedLinkedListActionType.Update, - SortedLinkedListActionType.Remove, - ]) - if (action === SortedLinkedListActionType.Remove) { - listKeys.delete(key.toNumber()) - } - } else { - action = SortedLinkedListActionType.Insert - listKeys.add(key.toNumber()) - } - sequence.push({ - actionType: action, - element: { - key, - value: BigNumber.random(20).shiftedBy(20), - }, - }) - } - return sequence - } - - const parseElements = (keys: BigNumber[], values: BigNumber[]): SortedElement[] => { - const elements = [] - for (let i = 0; i < keys.length; i++) { - elements.push({ - key: keys[i], - value: values[i], - }) - } - return elements - } - - const assertSorted = (elements: SortedElement[]) => { - for (let i = 0; i < elements.length; i++) { - if (i > 0) { - assert.isTrue(elements[i].value.lte(elements[i - 1].value), 'Elements not sorted') - } - } - } - - const assertSortedLinkedListInvariants = async ( - elementsPromise: Promise<[BigNumber[], BigNumber[]]>, - numElementsPromise: Promise, - headPromise: Promise, - tailPromise: Promise, - expectedKeys: Set - ) => { - const [keys, values] = await elementsPromise - const elements = parseElements(keys, values) - assert.equal( - (await numElementsPromise).toNumber(), - expectedKeys.size, - 'Incorrect number of elements' - ) - assert.equal(elements.length, expectedKeys.size, 'Incorrect number of elements') - assertSorted(elements) - if (elements.length > 0) { - assert.equal((await headPromise).toNumber(), elements[0].key.toNumber()) - assert.equal((await tailPromise).toNumber(), elements[elements.length - 1].key.toNumber()) - } else { - assert.equal((await headPromise).toNumber(), 0) - assert.equal((await tailPromise).toNumber(), 0) - } - } - - const doActionsAndAssertInvariants = async ( - numActions: number, - numKeys: number, - getLesserAndGreater: any, - allowFailingTx: boolean = false - ) => { - const sequence = makeActionSequence(numActions, numKeys) - const listKeys = new Set([]) - let successes = 0 - for (let i = 0; i < numActions; i++) { - const action = sequence[i] - try { - if (action.actionType === SortedLinkedListActionType.Remove) { - await sortedListTest.remove(action.element.key) - listKeys.delete(action.element.key.toNumber()) - } else { - const { lesser, greater } = await getLesserAndGreater(action.element) - if (action.actionType === SortedLinkedListActionType.Insert) { - await sortedListTest.insert(action.element.key, action.element.value, lesser, greater) - listKeys.add(action.element.key.toNumber()) - } else if (action.actionType === SortedLinkedListActionType.Update) { - await sortedListTest.update(action.element.key, action.element.value, lesser, greater) - } - } - successes += 1 - } catch (e) { - if (!allowFailingTx) { - throw new Error(e) - } - } - await assertSortedLinkedListInvariants( - sortedListTest.getElements(), - sortedListTest.getNumElements(), - sortedListTest.head(), - sortedListTest.tail(), - listKeys - ) - } - if (allowFailingTx) { - const expectedSuccessRate = 2.0 / numKeys - assert.isAtLeast(successes / numActions, expectedSuccessRate * 0.75) - } - } - - it('should maintain invariants when lesser and greater are correct', async () => { - const numActions = 100 - const numKeys = 20 - const getLesserAndGreater = async (element: SortedElement) => { - const [keys, values] = await sortedListTest.getElements() - const elements = parseElements(keys, values) - let lesser = new BigNumber(0) - let greater = new BigNumber(0) - for (let i = 0; i < elements.length; i++) { - if (!elements[i].key.eq(element.key)) { - if (elements[i].value.gte(element.value)) { - greater = elements[i].key - } - } - const j = elements.length - i - 1 - - if (!elements[j].key.eq(element.key)) { - if (elements[j].value.lte(element.value)) { - lesser = elements[j].key - } - } - } - return { lesser, greater } - } - await doActionsAndAssertInvariants(numActions, numKeys, getLesserAndGreater) - }) - - it('should maintain invariants when lesser and greater are incorrect', async () => { - const numReports = 200 - const numKeys = 10 - const getRandomKeys = async () => { - const [keys] = await sortedListTest.getElements() - - const getLesserOrGreater = () => { - const r = BigNumber.random() - const nonElement = () => { - let i = 0 - while (keys.includes(new BigNumber(i))) { - i++ - } - return new BigNumber(i) - } - if (r.isLessThan(0.33)) { - return randomElement(keys) - } else if (r.isLessThan(0.66)) { - return nonElement() - } else { - return new BigNumber(0) - } - } - return { lesser: getLesserOrGreater(), greater: getLesserOrGreater() } - } - await doActionsAndAssertInvariants(numReports, numKeys, getRandomKeys, true) - }) - }) -}) diff --git a/packages/protocol/test/governance/validators/validators.ts b/packages/protocol/test/governance/validators/validators.ts deleted file mode 100644 index 972968b3f..000000000 --- a/packages/protocol/test/governance/validators/validators.ts +++ /dev/null @@ -1,2817 +0,0 @@ -import { NULL_ADDRESS } from '@celo/base/lib/address' -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { getParsedSignatureOfAddress } from '@celo/protocol/lib/signing-utils' -import { - assertContainSubset, - assertEqualBN, - assertEqualBNArray, - assertEqualDpBN, - assertRevert, - assertSameAddress, - assertTransactionRevertWithReason, - currentEpochNumber, - mineBlocks, - mineToNextEpoch, - timeTravel, -} from '@celo/protocol/lib/test-utils' -import { fixed1, fromFixed, toFixed } from '@celo/utils/lib/fixidity' -import { addressToPublicKey } from '@celo/utils/lib/signatureUtils' -import BigNumber from 'bignumber.js' -import { - AccountsContract, - AccountsInstance, - MockElectionContract, - MockElectionInstance, - MockLockedGoldContract, - MockLockedGoldInstance, - MockStableTokenContract, - MockStableTokenInstance, - RegistryContract, - RegistryInstance, - ValidatorsTestContract, - ValidatorsTestInstance, -} from 'types' - -const Accounts: AccountsContract = artifacts.require('Accounts') -const Validators: ValidatorsTestContract = artifacts.require('ValidatorsTest') -const MockElection: MockElectionContract = artifacts.require('MockElection') -const MockLockedGold: MockLockedGoldContract = artifacts.require('MockLockedGold') -const MockStableToken: MockStableTokenContract = artifacts.require('MockStableToken') -const Registry: RegistryContract = artifacts.require('Registry') - -// @ts-ignore -// TODO(mcortesi): Use BN -Validators.numberFormat = 'BigNumber' - -const parseValidatorParams = (validatorParams: any) => { - return { - ecdsaPublicKey: validatorParams[0], - blsPublicKey: validatorParams[1], - affiliation: validatorParams[2], - score: validatorParams[3], - signer: validatorParams[4], - } -} - -const parseValidatorGroupParams = (groupParams: any) => { - return { - members: groupParams[0], - commission: groupParams[1], - nextCommission: groupParams[2], - nextCommissionBlock: groupParams[3], - sizeHistory: groupParams[4], - slashingMultiplier: groupParams[5], - lastSlashed: groupParams[6], - } -} - -const parseMembershipHistory = (membershipHistory: any) => { - return { - epochs: membershipHistory[0], - groups: membershipHistory[1], - lastRemovedFromGroupTimestamp: membershipHistory[2], - tail: membershipHistory[3], - } -} - -const HOUR = 60 * 60 -const DAY = 24 * HOUR - -contract('Validators', (accounts: string[]) => { - let accountsInstance: AccountsInstance - let validators: ValidatorsTestInstance - let registry: RegistryInstance - let mockElection: MockElectionInstance - let mockLockedGold: MockLockedGoldInstance - const nonOwner = accounts[1] - - const validatorLockedGoldRequirements = { - value: new BigNumber(1000), - duration: new BigNumber(60 * DAY), - } - const groupLockedGoldRequirements = { - value: new BigNumber(1000), - duration: new BigNumber(100 * DAY), - } - const validatorScoreParameters = { - exponent: new BigNumber(5), - adjustmentSpeed: toFixed(0.25), - } - - const one = new BigNumber(1) - const max1 = (num: BigNumber) => (num.gt(one) ? one : num) - const calculateScore = (uptime: BigNumber, gracePeriod: BigNumber) => - max1(uptime.plus(gracePeriod)).pow(validatorScoreParameters.exponent) - - const slashingMultiplierResetPeriod = 30 * DAY - const membershipHistoryLength = new BigNumber(5) - const maxGroupSize = new BigNumber(5) - const commissionUpdateDelay = new BigNumber(3) - const downtimeGracePeriod = new BigNumber(0) - - // A random 64 byte hex string. - const blsPublicKey = - '0x4fa3f67fc913878b068d1fa1cdddc54913d3bf988dbe5a36a20fa888f20d4894c408a6773f3d7bde11154f2a3076b700d345a42fd25a0e5e83f4db5586ac7979ac2053cd95d8f2efd3e959571ceccaa743e02cf4be3f5d7aaddb0b06fc9aff00' - const blsPoP = - '0xcdb77255037eb68897cd487fdd85388cbda448f617f874449d4b11588b0b7ad8ddc20d9bb450b513bb35664ea3923900' - const commission = toFixed(1 / 100) - beforeEach(async () => { - accountsInstance = await Accounts.new(true) - // Do not register an account for the last address so it can be used as an authorized validator signer. - await Promise.all( - accounts.slice(0, -1).map((account) => accountsInstance.createAccount({ from: account })) - ) - mockElection = await MockElection.new() - mockLockedGold = await MockLockedGold.new() - registry = await Registry.new(true) - validators = await Validators.new() - await accountsInstance.initialize(registry.address) - await registry.setAddressFor(CeloContractName.Accounts, accountsInstance.address) - await registry.setAddressFor(CeloContractName.Election, mockElection.address) - await registry.setAddressFor(CeloContractName.LockedGold, mockLockedGold.address) - await registry.setAddressFor(CeloContractName.Validators, validators.address) - await validators.initialize( - registry.address, - groupLockedGoldRequirements.value, - groupLockedGoldRequirements.duration, - validatorLockedGoldRequirements.value, - validatorLockedGoldRequirements.duration, - validatorScoreParameters.exponent, - validatorScoreParameters.adjustmentSpeed, - membershipHistoryLength, - slashingMultiplierResetPeriod, - maxGroupSize, - commissionUpdateDelay, - downtimeGracePeriod - ) - }) - - const registerValidator = async (validator: string) => { - await mockLockedGold.setAccountTotalLockedGold(validator, validatorLockedGoldRequirements.value) - const publicKey = await addressToPublicKey(validator, web3.eth.sign) - await validators.registerValidator(publicKey, blsPublicKey, blsPoP, { from: validator }) - } - - const registerValidatorGroup = async (group: string, numMembers: number = 1) => { - await mockLockedGold.setAccountTotalLockedGold( - group, - groupLockedGoldRequirements.value.times(numMembers) - ) - await validators.registerValidatorGroup(commission, { from: group }) - } - - const registerValidatorGroupWithMembers = async (group: string, members: string[]) => { - await registerValidatorGroup(group, members.length) - for (const validator of members) { - await registerValidator(validator) - await validators.affiliate(group, { from: validator }) - if (validator === members[0]) { - await validators.addFirstMember(validator, NULL_ADDRESS, NULL_ADDRESS, { from: group }) - } else { - await validators.addMember(validator, { from: group }) - } - } - } - - describe('#initialize()', () => { - it('should have set the owner', async () => { - const owner: string = await validators.owner() - assert.equal(owner, accounts[0]) - }) - - it('should have set the group locked gold requirements', async () => { - const [value, duration] = await validators.getGroupLockedGoldRequirements() - assertEqualBN(value, groupLockedGoldRequirements.value) - assertEqualBN(duration, groupLockedGoldRequirements.duration) - }) - - it('should have set the validator locked gold requirements', async () => { - const [value, duration] = await validators.getValidatorLockedGoldRequirements() - assertEqualBN(value, validatorLockedGoldRequirements.value) - assertEqualBN(duration, validatorLockedGoldRequirements.duration) - }) - - it('should have set the validator score parameters', async () => { - const [exponent, adjustmentSpeed] = await validators.getValidatorScoreParameters() - assertEqualBN(exponent, validatorScoreParameters.exponent) - assertEqualBN(adjustmentSpeed, validatorScoreParameters.adjustmentSpeed) - }) - - it('should have set the membership history length', async () => { - const actual = await validators.membershipHistoryLength() - assertEqualBN(actual, membershipHistoryLength) - }) - - it('should have set the max group size', async () => { - const actualMaxGroupSize = await validators.getMaxGroupSize() - assertEqualBN(actualMaxGroupSize, maxGroupSize) - }) - - it('should have set the commision update delay', async () => { - const actualCommissionUpdateDelay = await validators.getCommissionUpdateDelay() - assertEqualBN(actualCommissionUpdateDelay, commissionUpdateDelay) - }) - - it('should have set the downtime grace period', async () => { - const actualDowntimeGracePeriod = await validators.downtimeGracePeriod() - assertEqualBN(actualDowntimeGracePeriod, downtimeGracePeriod) - }) - - it('should not be callable again', async () => { - await assertTransactionRevertWithReason( - validators.initialize( - registry.address, - groupLockedGoldRequirements.value, - groupLockedGoldRequirements.duration, - validatorLockedGoldRequirements.value, - validatorLockedGoldRequirements.duration, - validatorScoreParameters.exponent, - validatorScoreParameters.adjustmentSpeed, - membershipHistoryLength, - slashingMultiplierResetPeriod, - maxGroupSize, - commissionUpdateDelay, - downtimeGracePeriod - ), - 'contract already initialized' - ) - }) - }) - - describe('#setMembershipHistoryLength()', () => { - describe('when the length is different', () => { - const newLength = membershipHistoryLength.plus(1) - - describe('when called by the owner', () => { - let resp: any - - beforeEach(async () => { - resp = await validators.setMembershipHistoryLength(newLength) - }) - - it('should set the membership history length', async () => { - assertEqualBN(await validators.membershipHistoryLength(), newLength) - }) - - it('should emit the MembershipHistoryLengthSet event', async () => { - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'MembershipHistoryLengthSet', - args: { - length: new BigNumber(newLength), - }, - }) - }) - - describe('when called by a non-owner', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.setMembershipHistoryLength(newLength, { - from: nonOwner, - }), - 'Ownable: caller is not the owner' - ) - }) - }) - }) - - describe('when the length is the same', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.setMembershipHistoryLength(membershipHistoryLength), - 'Membership history length not changed' - ) - }) - }) - }) - }) - - describe('#setMaxGroupSize()', () => { - describe('when the group size is different', () => { - const newSize = maxGroupSize.plus(1) - - describe('when called by the owner', () => { - let resp: any - - beforeEach(async () => { - resp = await validators.setMaxGroupSize(newSize) - }) - - it('should set the max group size', async () => { - assertEqualBN(await validators.maxGroupSize(), newSize) - }) - - it('should emit the MaxGroupSizeSet event', async () => { - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'MaxGroupSizeSet', - args: { - size: new BigNumber(newSize), - }, - }) - }) - - describe('when called by a non-owner', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.setMaxGroupSize(newSize, { - from: nonOwner, - }), - 'Ownable: caller is not the owner' - ) - }) - }) - }) - - describe('when the size is the same', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.setMaxGroupSize(maxGroupSize), - 'Max group size not changed' - ) - }) - }) - }) - }) - - describe('#setGroupLockedGoldRequirements()', () => { - describe('when the requirements are different', () => { - const newRequirements = { - value: groupLockedGoldRequirements.value.plus(1), - duration: groupLockedGoldRequirements.duration.plus(1), - } - - describe('when called by the owner', () => { - let resp: any - - beforeEach(async () => { - resp = await validators.setGroupLockedGoldRequirements( - newRequirements.value, - newRequirements.duration - ) - }) - - it('should have set the group locked gold requirements', async () => { - const [value, duration] = await validators.getGroupLockedGoldRequirements() - assertEqualBN(value, newRequirements.value) - assertEqualBN(duration, newRequirements.duration) - }) - - it('should emit the GroupLockedGoldRequirementsSet event', async () => { - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'GroupLockedGoldRequirementsSet', - args: { - value: newRequirements.value, - duration: newRequirements.duration, - }, - }) - }) - - describe('when called by a non-owner', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.setGroupLockedGoldRequirements( - newRequirements.value, - newRequirements.duration, - { from: nonOwner } - ), - 'Ownable: caller is not the owner' - ) - }) - }) - }) - - describe('when the requirements are the same', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.setGroupLockedGoldRequirements( - groupLockedGoldRequirements.value, - groupLockedGoldRequirements.duration - ), - 'Group requirements not changed' - ) - }) - }) - }) - }) - - describe('#setValidatorLockedGoldRequirements()', () => { - describe('when the requirements are different', () => { - const newRequirements = { - value: validatorLockedGoldRequirements.value.plus(1), - duration: validatorLockedGoldRequirements.duration.plus(1), - } - - describe('when called by the owner', () => { - let resp: any - - beforeEach(async () => { - resp = await validators.setValidatorLockedGoldRequirements( - newRequirements.value, - newRequirements.duration - ) - }) - - it('should have set the validator locked gold requirements', async () => { - const [value, duration] = await validators.getValidatorLockedGoldRequirements() - assertEqualBN(value, newRequirements.value) - assertEqualBN(duration, newRequirements.duration) - }) - - it('should emit the ValidatorLockedGoldRequirementsSet event', async () => { - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ValidatorLockedGoldRequirementsSet', - args: { - value: newRequirements.value, - duration: newRequirements.duration, - }, - }) - }) - - describe('when called by a non-owner', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.setValidatorLockedGoldRequirements( - newRequirements.value, - newRequirements.duration, - { from: nonOwner } - ), - 'Ownable: caller is not the owner' - ) - }) - }) - }) - - describe('when the requirements are the same', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.setValidatorLockedGoldRequirements( - validatorLockedGoldRequirements.value, - validatorLockedGoldRequirements.duration - ), - 'Validator requirements not changed' - ) - }) - }) - }) - }) - - describe('#setValidatorScoreParameters()', () => { - describe('when the parameters are different', () => { - const newParameters = { - exponent: validatorScoreParameters.exponent.plus(1), - adjustmentSpeed: validatorScoreParameters.adjustmentSpeed.plus(1), - } - - describe('when called by the owner', () => { - let resp: any - - beforeEach(async () => { - resp = await validators.setValidatorScoreParameters( - newParameters.exponent, - newParameters.adjustmentSpeed - ) - }) - - it('should set the exponent and adjustment speed', async () => { - const [exponent, adjustmentSpeed] = await validators.getValidatorScoreParameters() - assertEqualBN(exponent, newParameters.exponent) - assertEqualBN(adjustmentSpeed, newParameters.adjustmentSpeed) - }) - - it('should emit the ValidatorScoreParametersSet event', async () => { - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ValidatorScoreParametersSet', - args: { - exponent: new BigNumber(newParameters.exponent), - adjustmentSpeed: new BigNumber(newParameters.adjustmentSpeed), - }, - }) - }) - - describe('when called by a non-owner', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.setValidatorScoreParameters( - newParameters.exponent, - newParameters.adjustmentSpeed, - { - from: nonOwner, - } - ), - 'Ownable: caller is not the owner' - ) - }) - }) - }) - - describe('when the lockups are the same', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.setValidatorScoreParameters( - validatorScoreParameters.exponent, - validatorScoreParameters.adjustmentSpeed - ), - 'Adjustment speed and exponent not changed' - ) - }) - }) - }) - }) - - describe('#setMaxGroupSize()', () => { - describe('when the size is different', () => { - describe('when called by the owner', () => { - let resp: any - const newSize = maxGroupSize.plus(1) - - beforeEach(async () => { - resp = await validators.setMaxGroupSize(newSize) - }) - - it('should set the max group size', async () => { - const size = await validators.getMaxGroupSize() - assertEqualBN(size, newSize) - }) - - it('should emit the MaxGroupSizeSet event', async () => { - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'MaxGroupSizeSet', - args: { - size: new BigNumber(newSize), - }, - }) - }) - }) - - describe('when the size is the same', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.setMaxGroupSize(maxGroupSize), - 'Max group size not changed' - ) - }) - }) - }) - - describe('when called by a non-owner', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.setMaxGroupSize(maxGroupSize, { from: nonOwner }), - 'Ownable: caller is not the owner' - ) - }) - }) - }) - - describe('#registerValidator', () => { - const validator = accounts[0] - let resp: any - describe('when the account is not a registered validator', () => { - beforeEach(async () => { - await mockLockedGold.setAccountTotalLockedGold( - validator, - validatorLockedGoldRequirements.value - ) - }) - - it('should revert when vote over max number of groups set to true', async () => { - await mockElection.setAllowedToVoteOverMaxNumberOfGroups(validator, true) - const signer = accounts[9] - const sig = await getParsedSignatureOfAddress(web3, validator, signer) - await accountsInstance.authorizeValidatorSigner(signer, sig.v, sig.r, sig.s) - const publicKey = await addressToPublicKey(signer, web3.eth.sign) - await assertTransactionRevertWithReason( - validators.registerValidator(publicKey, blsPublicKey, blsPoP), - 'Cannot vote for more than max number of groups' - ) - }) - - it('should revert when delegating Celo', async () => { - await mockLockedGold.setAccountTotalDelegatedAmountInPercents(validator, 10) - const signer = accounts[9] - const sig = await getParsedSignatureOfAddress(web3, validator, signer) - await accountsInstance.authorizeValidatorSigner(signer, sig.v, sig.r, sig.s) - const publicKey = await addressToPublicKey(signer, web3.eth.sign) - await assertTransactionRevertWithReason( - validators.registerValidator(publicKey, blsPublicKey, blsPoP), - 'Cannot delegate governance power' - ) - }) - - describe('when the account has authorized a validator signer', () => { - let validatorRegistrationEpochNumber: number - let publicKey: string - let signer: string - beforeEach(async () => { - signer = accounts[9] - const sig = await getParsedSignatureOfAddress(web3, validator, signer) - await accountsInstance.authorizeValidatorSigner(signer, sig.v, sig.r, sig.s) - publicKey = await addressToPublicKey(signer, web3.eth.sign) - resp = await validators.registerValidator(publicKey, blsPublicKey, blsPoP) - validatorRegistrationEpochNumber = await currentEpochNumber(web3) - }) - - it('should mark the account as a validator', async () => { - assert.isTrue(await validators.isValidator(validator)) - }) - - it('should add the account to the list of validators', async () => { - assert.deepEqual(await validators.getRegisteredValidators(), [validator]) - }) - - it('should set the validator ecdsa public key', async () => { - const parsedValidator = parseValidatorParams(await validators.getValidator(validator)) - assert.equal(parsedValidator.ecdsaPublicKey, publicKey) - }) - - it('should set the validator bls public key', async () => { - const parsedValidator = parseValidatorParams(await validators.getValidator(validator)) - assert.equal(parsedValidator.blsPublicKey, blsPublicKey) - }) - - it('should set the validator signer', async () => { - const parsedValidator = parseValidatorParams(await validators.getValidator(validator)) - assert.equal(parsedValidator.signer, signer) - }) - - it('should set account locked gold requirements', async () => { - const requirement = await validators.getAccountLockedGoldRequirement(validator) - assertEqualBN(requirement, validatorLockedGoldRequirements.value) - }) - - it('should set the validator membership history', async () => { - const membershipHistory = await validators.getMembershipHistory(validator) - assertEqualBNArray(membershipHistory[0], [validatorRegistrationEpochNumber]) - assert.deepEqual(membershipHistory[1], [NULL_ADDRESS]) - }) - - it('should set the validator membership history', async () => { - const membershipHistory = await validators.getMembershipHistory(validator) - assertEqualBNArray(membershipHistory[0], [validatorRegistrationEpochNumber]) - assert.deepEqual(membershipHistory[1], [NULL_ADDRESS]) - }) - - it('should emit the ValidatorEcdsaPublicKeyUpdated, ValidatorBlsPublicKeyUpdated, and ValidatorRegistered events', async () => { - assert.equal(resp.logs.length, 3) - assertContainSubset(resp.logs[0], { - event: 'ValidatorEcdsaPublicKeyUpdated', - args: { - validator, - ecdsaPublicKey: publicKey, - }, - }) - assertContainSubset(resp.logs[1], { - event: 'ValidatorBlsPublicKeyUpdated', - args: { - validator, - blsPublicKey, - }, - }) - assertContainSubset(resp.logs[2], { - event: 'ValidatorRegistered', - args: { - validator, - }, - }) - }) - }) - }) - - describe('when the account is already a registered validator ', () => { - let publicKey: string - beforeEach(async () => { - await mockLockedGold.setAccountTotalLockedGold( - validator, - validatorLockedGoldRequirements.value - ) - }) - - it('should revert', async () => { - publicKey = await addressToPublicKey(validator, web3.eth.sign) - await validators.registerValidator(publicKey, blsPublicKey, blsPoP) - await assertTransactionRevertWithReason( - validators.registerValidator(publicKey, blsPublicKey, blsPoP), - 'Already registered' - ) - }) - }) - - describe('when the account is already a registered validator group', () => { - beforeEach(async () => { - await mockLockedGold.setAccountTotalLockedGold(validator, groupLockedGoldRequirements.value) - await validators.registerValidatorGroup(commission) - }) - - it('should revert', async () => { - const publicKey = await addressToPublicKey(validator, web3.eth.sign) - await assertTransactionRevertWithReason( - validators.registerValidator(publicKey, blsPublicKey, blsPoP), - 'Already registered' - ) - }) - }) - - describe('when the account does not meet the locked gold requirements', () => { - beforeEach(async () => { - await mockLockedGold.setAccountTotalLockedGold( - validator, - validatorLockedGoldRequirements.value.minus(11) - ) - }) - - it('should revert', async () => { - const publicKey = await addressToPublicKey(validator, web3.eth.sign) - await assertTransactionRevertWithReason( - validators.registerValidator(publicKey, blsPublicKey, blsPoP), - 'Deposit too small' - ) - }) - }) - }) - - describe('#deregisterValidator', () => { - const validator = accounts[0] - const index = 0 - let resp: any - describe('when the account is a registered validator', () => { - beforeEach(async () => { - await registerValidator(validator) - }) - - describe('when the validator has never been a member of a validator group', () => { - beforeEach(async () => { - resp = await validators.deregisterValidator(index) - }) - - it('should mark the account as not a validator', async () => { - assert.isFalse(await validators.isValidator(validator)) - }) - - it('should remove the account from the list of validators', async () => { - assert.deepEqual(await validators.getRegisteredValidators(), []) - }) - - it('should reset account balance requirements', async () => { - const requirement = await validators.getAccountLockedGoldRequirement(validator) - assertEqualBN(requirement, 0) - }) - - it('should emit the ValidatorDeregistered event', async () => { - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ValidatorDeregistered', - args: { - validator, - }, - }) - }) - }) - - describe('when the validator has been a member of a validator group', () => { - const group = accounts[1] - beforeEach(async () => { - await registerValidatorGroup(group) - await validators.affiliate(group) - await validators.addFirstMember(validator, NULL_ADDRESS, NULL_ADDRESS, { from: group }) - }) - - describe('when the validator is no longer a member of a validator group', () => { - beforeEach(async () => { - await validators.removeMember(validator, { from: group }) - }) - - describe('when it has been more than `validatorLockedGoldRequirements.duration` since the validator was removed from the group', () => { - beforeEach(async () => { - await timeTravel(validatorLockedGoldRequirements.duration.plus(1).toNumber(), web3) - resp = await validators.deregisterValidator(index) - }) - - it('should mark the account as not a validator', async () => { - assert.isFalse(await validators.isValidator(validator)) - }) - - it('should remove the account from the list of validators', async () => { - assert.deepEqual(await validators.getRegisteredValidators(), []) - }) - - it('should reset account balance requirements', async () => { - const requirement = await validators.getAccountLockedGoldRequirement(validator) - assertEqualBN(requirement, 0) - }) - - it('should emit the ValidatorDeregistered event', async () => { - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ValidatorDeregistered', - args: { - validator, - }, - }) - }) - }) - - describe('when it has been less than `validatorLockedGoldRequirements.duration` since the validator was removed from the group', () => { - beforeEach(async () => { - await timeTravel(validatorLockedGoldRequirements.duration.minus(1).toNumber(), web3) - }) - - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.deregisterValidator(index), - 'Not yet requirement end time' - ) - }) - }) - }) - - describe('when the validator is still a member of a validator group', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.deregisterValidator(index), - 'Has been group member recently' - ) - }) - }) - }) - }) - - it('should revert when the account is not a registered validator', async () => { - await assertTransactionRevertWithReason( - validators.deregisterValidator(index, { from: accounts[2] }), - 'Not a validator' - ) - }) - - it('should revert when the wrong index is provided', async () => { - await assertTransactionRevertWithReason( - validators.deregisterValidator(index + 1), - 'Not a validator' - ) - }) - }) - - describe('#affiliate', () => { - const validator = accounts[0] - const group = accounts[1] - let registrationEpoch: number - let resp: any - describe('when the account has a registered validator', () => { - beforeEach(async () => { - await registerValidator(validator) - registrationEpoch = await currentEpochNumber(web3) - }) - describe('when affiliating with a registered validator group', () => { - beforeEach(async () => { - await registerValidatorGroup(group) - }) - - describe('when the validator meets the locked gold requirements', () => { - describe('when the group meets the locked gold requirements', () => { - beforeEach(async () => { - resp = await validators.affiliate(group) - }) - - it('should set the affiliate', async () => { - await validators.affiliate(group) - const parsedValidator = parseValidatorParams(await validators.getValidator(validator)) - assert.equal(parsedValidator.affiliation, group) - }) - - it('should emit the ValidatorAffiliated event', async () => { - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ValidatorAffiliated', - args: { - validator, - group, - }, - }) - }) - - describe('when the validator is already affiliated with a validator group', () => { - const otherGroup = accounts[2] - beforeEach(async () => { - await registerValidatorGroup(otherGroup) - }) - - describe('when the validator is not a member of that validator group', () => { - beforeEach(async () => { - resp = await validators.affiliate(otherGroup) - }) - - it('should set the affiliate', async () => { - const parsedValidator = parseValidatorParams( - await validators.getValidator(validator) - ) - assert.equal(parsedValidator.affiliation, otherGroup) - }) - - it('should emit the ValidatorDeaffilliated event', async () => { - assert.equal(resp.logs.length, 2) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ValidatorDeaffiliated', - args: { - validator, - group, - }, - }) - }) - - it('should emit the ValidatorAffiliated event', async () => { - assert.equal(resp.logs.length, 2) - const log = resp.logs[1] - assertContainSubset(log, { - event: 'ValidatorAffiliated', - args: { - validator, - group: otherGroup, - }, - }) - }) - }) - - describe('when the validator is a member of that group', () => { - let additionEpoch: number - let affiliationEpoch: number - beforeEach(async () => { - await validators.addFirstMember(validator, NULL_ADDRESS, NULL_ADDRESS, { - from: group, - }) - additionEpoch = await currentEpochNumber(web3) - resp = await validators.affiliate(otherGroup) - affiliationEpoch = await currentEpochNumber(web3) - }) - - it('should remove the validator from the group membership list', async () => { - const parsedGroup = parseValidatorGroupParams( - await validators.getValidatorGroup(group) - ) - assert.deepEqual(parsedGroup.members, []) - }) - - it("should update the validator's membership history", async () => { - const membershipHistory = parseMembershipHistory( - await validators.getMembershipHistory(validator) - ) - let expectedEntries = 1 - if (registrationEpoch !== additionEpoch || additionEpoch !== affiliationEpoch) { - expectedEntries = 2 - } - assert.equal(membershipHistory.epochs.length, expectedEntries) - assertEqualBN(membershipHistory.epochs[expectedEntries - 1], affiliationEpoch) - assert.equal(membershipHistory.groups.length, expectedEntries) - assertSameAddress(membershipHistory.groups[expectedEntries - 1], NULL_ADDRESS) - const latestBlock = await web3.eth.getBlock('latest') - assert.equal( - membershipHistory.lastRemovedFromGroupTimestamp, - latestBlock.timestamp - ) - }) - - it('should emit the ValidatorGroupMemberRemoved event', async () => { - assert.equal(resp.logs.length, 3) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ValidatorGroupMemberRemoved', - args: { - validator, - group, - }, - }) - }) - - describe('when the validator is the only member of that group', () => { - it('should should mark the group as ineligible for election', async () => { - assert.isTrue(await mockElection.isIneligible(group)) - }) - }) - }) - }) - }) - - describe('when the group does not meet the locked gold requirements', () => { - beforeEach(async () => { - await mockLockedGold.setAccountTotalLockedGold( - group, - groupLockedGoldRequirements.value.minus(11) - ) - }) - - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.affiliate(group), - "Group doesn't meet requirements" - ) - }) - }) - }) - - describe('when the validator does not meet the locked gold requirements', () => { - beforeEach(async () => { - await mockLockedGold.setAccountTotalLockedGold( - validator, - validatorLockedGoldRequirements.value.minus(11) - ) - }) - - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.affiliate(group), - "Validator doesn't meet requirements" - ) - }) - }) - }) - - describe('when affiliating with a non-registered validator group', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.affiliate(group), - 'Not a validator group' - ) - }) - }) - }) - - describe('when the account does not have a registered validator', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason(validators.affiliate(group), 'Not a validator') - }) - }) - }) - - describe('#deaffiliate', () => { - const validator = accounts[0] - const group = accounts[1] - let registrationEpoch: number - beforeEach(async () => { - await registerValidator(validator) - registrationEpoch = await currentEpochNumber(web3) - await registerValidatorGroup(group) - await validators.affiliate(group) - }) - - it('should clear the affiliate', async () => { - await validators.deaffiliate() - const parsedValidator = parseValidatorParams(await validators.getValidator(validator)) - assert.equal(parsedValidator.affiliation, NULL_ADDRESS) - }) - - it('should emit the ValidatorDeaffiliated event', async () => { - const resp = await validators.deaffiliate() - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ValidatorDeaffiliated', - args: { - validator, - group, - }, - }) - }) - - describe('when the validator is a member of the affiliated group', () => { - let additionEpoch: number - let deaffiliationEpoch: number - let resp: any - beforeEach(async () => { - await validators.addFirstMember(validator, NULL_ADDRESS, NULL_ADDRESS, { from: group }) - additionEpoch = await currentEpochNumber(web3) - resp = await validators.deaffiliate() - deaffiliationEpoch = await currentEpochNumber(web3) - }) - - it('should remove the validator from the group membership list', async () => { - const parsedGroup = parseValidatorGroupParams(await validators.getValidatorGroup(group)) - assert.deepEqual(parsedGroup.members, []) - }) - - it("should update the member's membership history", async () => { - const membershipHistory = parseMembershipHistory( - await validators.getMembershipHistory(validator) - ) - let expectedEntries = 1 - if (registrationEpoch !== additionEpoch || additionEpoch !== deaffiliationEpoch) { - expectedEntries = 2 - } - assert.equal(membershipHistory.epochs.length, expectedEntries) - assertEqualBN(membershipHistory.epochs[expectedEntries - 1], deaffiliationEpoch) - assert.equal(membershipHistory.groups.length, expectedEntries) - assertSameAddress(membershipHistory.groups[expectedEntries - 1], NULL_ADDRESS) - const latestBlock = await web3.eth.getBlock('latest') - assert.equal(membershipHistory.lastRemovedFromGroupTimestamp, latestBlock.timestamp) - }) - - it('should emit the ValidatorGroupMemberRemoved event', async () => { - assert.equal(resp.logs.length, 2) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ValidatorGroupMemberRemoved', - args: { - validator, - group, - }, - }) - }) - - describe('when the validator is the only member of that group', () => { - it('should should mark the group as ineligible for election', async () => { - assert.isTrue(await mockElection.isIneligible(group)) - }) - }) - }) - - it('should revert when the account is not a registered validator', async () => { - await assertTransactionRevertWithReason( - validators.deaffiliate({ from: accounts[2] }), - 'Not a validator' - ) - }) - - it('should revert when the validator is not affiliated with a validator group', async () => { - await validators.deaffiliate() - await assertTransactionRevertWithReason(validators.deaffiliate(), 'not affiliated') - }) - }) - - describe('#updateEcdsaPublicKey()', () => { - describe('when called by a registered validator', () => { - const validator = accounts[0] - beforeEach(async () => { - await registerValidator(validator) - }) - - describe('when called by the registered `Accounts` contract', () => { - beforeEach(async () => { - await registry.setAddressFor(CeloContractName.Accounts, accounts[0]) - }) - - describe('when the public key matches the signer', () => { - let resp: any - let newPublicKey: string - const signer = accounts[9] - beforeEach(async () => { - newPublicKey = await addressToPublicKey(signer, web3.eth.sign) - resp = await validators.updateEcdsaPublicKey(validator, signer, newPublicKey) - }) - - it('should set the validator ecdsa public key', async () => { - await registry.setAddressFor(CeloContractName.Accounts, accountsInstance.address) - const parsedValidator = parseValidatorParams(await validators.getValidator(validator)) - assert.equal(parsedValidator.ecdsaPublicKey, newPublicKey) - }) - - it('should emit the ValidatorEcdsaPublicKeyUpdated event', async () => { - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ValidatorEcdsaPublicKeyUpdated', - args: { - validator, - ecdsaPublicKey: newPublicKey, - }, - }) - }) - }) - - describe('when the public key does not match the signer', () => { - const signer = accounts[9] - it('should revert', async () => { - const newPublicKey = await addressToPublicKey(accounts[8], web3.eth.sign) - await assertTransactionRevertWithReason( - validators.updateEcdsaPublicKey(validator, signer, newPublicKey), - 'ECDSA key does not match signer' - ) - }) - }) - }) - - describe('when not called by the registered `Accounts` contract', () => { - describe('when the public key matches the signer', () => { - const signer = accounts[9] - it('should revert', async () => { - const newPublicKey = await addressToPublicKey(signer, web3.eth.sign) - await assertTransactionRevertWithReason( - validators.updateEcdsaPublicKey(validator, signer, newPublicKey), - 'only registered contract' - ) - }) - }) - }) - }) - }) - - describe('#updatePublicKeys()', () => { - const newBlsPublicKey: string = web3.utils.randomHex(96) - const newBlsPoP: string = web3.utils.randomHex(48) - describe('when called by a registered validator', () => { - const validator = accounts[0] - beforeEach(async () => { - await registerValidator(validator) - }) - - describe('when called by the registered `Accounts` contract', () => { - beforeEach(async () => { - await registry.setAddressFor(CeloContractName.Accounts, accounts[0]) - }) - - describe('when the public key matches the signer', () => { - let resp: any - let newPublicKey: string - const signer = accounts[9] - beforeEach(async () => { - newPublicKey = await addressToPublicKey(signer, web3.eth.sign) - resp = await validators.updatePublicKeys( - validator, - signer, - newPublicKey, - newBlsPublicKey, - newBlsPoP - ) - }) - - it('should set the validator ecdsa public key', async () => { - await registry.setAddressFor(CeloContractName.Accounts, accountsInstance.address) - const parsedValidator = parseValidatorParams(await validators.getValidator(validator)) - assert.equal(parsedValidator.ecdsaPublicKey, newPublicKey) - }) - - it('should emit the events', async () => { - assert.equal(resp.logs.length, 2) - assertContainSubset(resp.logs[0], { - event: 'ValidatorEcdsaPublicKeyUpdated', - args: { - validator, - ecdsaPublicKey: newPublicKey, - }, - }) - assertContainSubset(resp.logs[1], { - event: 'ValidatorBlsPublicKeyUpdated', - args: { - validator, - blsPublicKey: newBlsPublicKey, - }, - }) - }) - }) - - describe('when the public key does not match the signer', () => { - const signer = accounts[9] - it('should revert', async () => { - const newPublicKey = await addressToPublicKey(accounts[8], web3.eth.sign) - await assertTransactionRevertWithReason( - validators.updatePublicKeys( - validator, - signer, - newPublicKey, - newBlsPublicKey, - newBlsPoP - ), - 'ECDSA key does not match signer' - ) - }) - }) - }) - - describe('when not called by the registered `Accounts` contract', () => { - describe('when the public key matches the signer', () => { - const signer = accounts[9] - it('should revert', async () => { - const newPublicKey = await addressToPublicKey(signer, web3.eth.sign) - await assertTransactionRevertWithReason( - validators.updatePublicKeys( - validator, - signer, - newPublicKey, - newBlsPublicKey, - newBlsPoP - ), - 'only registered contract' - ) - }) - }) - }) - }) - }) - - describe('#updateBlsPublicKey()', () => { - const newBlsPublicKey = web3.utils.randomHex(96) - const newBlsPoP = web3.utils.randomHex(48) - describe('when called by a registered validator', () => { - const validator = accounts[0] - beforeEach(async () => { - await registerValidator(validator) - }) - - describe('when the keys are the right length', () => { - let resp: any - beforeEach(async () => { - resp = await validators.updateBlsPublicKey(newBlsPublicKey, newBlsPoP) - }) - - it('should set the validator bls public key', async () => { - const parsedValidator = parseValidatorParams(await validators.getValidator(validator)) - assert.equal(parsedValidator.blsPublicKey, newBlsPublicKey) - }) - - it('should emit the ValidatorBlsPublicKeyUpdated event', async () => { - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ValidatorBlsPublicKeyUpdated', - args: { - validator, - blsPublicKey: newBlsPublicKey, - }, - }) - }) - }) - - describe('when the public key is not 96 bytes', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.updateBlsPublicKey(newBlsPublicKey + '01', newBlsPoP), - 'Wrong BLS public key length' - ) - }) - }) - - describe('when the proof of possession is not 48 bytes', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.updateBlsPublicKey(newBlsPublicKey, newBlsPoP + '01'), - 'Wrong BLS PoP length' - ) - }) - }) - }) - }) - - describe('#registerValidatorGroup', () => { - const group = accounts[0] - let resp: any - describe('when the account is not a registered validator group', () => { - it('should revert when vote over max number of groups set to true', async () => { - await mockElection.setAllowedToVoteOverMaxNumberOfGroups(group, true) - const signer = accounts[9] - const sig = await getParsedSignatureOfAddress(web3, group, signer) - await accountsInstance.authorizeValidatorSigner(signer, sig.v, sig.r, sig.s) - const publicKey = await addressToPublicKey(signer, web3.eth.sign) - await assertTransactionRevertWithReason( - validators.registerValidator(publicKey, blsPublicKey, blsPoP), - 'Cannot vote for more than max number of groups' - ) - }) - - it('should revert when vote over max number of groups set to true', async () => { - await mockElection.setAllowedToVoteOverMaxNumberOfGroups(group, true) - await mockLockedGold.setAccountTotalLockedGold(group, groupLockedGoldRequirements.value) - await assertTransactionRevertWithReason( - validators.registerValidatorGroup(commission), - 'Cannot vote for more than max number of groups' - ) - }) - - it('should revert when vote over max number of groups set to true', async () => { - await mockLockedGold.setAccountTotalDelegatedAmountInPercents(group, 10) - await mockLockedGold.setAccountTotalLockedGold(group, groupLockedGoldRequirements.value) - await assertTransactionRevertWithReason( - validators.registerValidatorGroup(commission), - 'Cannot delegate governance power' - ) - }) - - describe('when the account meets the locked gold requirements', () => { - beforeEach(async () => { - await mockLockedGold.setAccountTotalLockedGold(group, groupLockedGoldRequirements.value) - resp = await validators.registerValidatorGroup(commission) - }) - - it('should mark the account as a validator group', async () => { - assert.isTrue(await validators.isValidatorGroup(group)) - }) - - it('should add the account to the list of validator groups', async () => { - assert.deepEqual(await validators.getRegisteredValidatorGroups(), [group]) - }) - - it('should set the validator group commission', async () => { - const parsedGroup = parseValidatorGroupParams(await validators.getValidatorGroup(group)) - assertEqualBN(parsedGroup.commission, commission) - }) - - it('should set account locked gold requirements', async () => { - const requirement = await validators.getAccountLockedGoldRequirement(group) - assertEqualBN(requirement, groupLockedGoldRequirements.value) - }) - - it('should emit the ValidatorGroupRegistered event', async () => { - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ValidatorGroupRegistered', - args: { - group, - commission, - }, - }) - }) - }) - - describe('when the account does not meet the locked gold requirements', () => { - beforeEach(async () => { - await mockLockedGold.setAccountTotalLockedGold( - group, - groupLockedGoldRequirements.value.minus(11) - ) - }) - - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.registerValidatorGroup(commission), - 'Not enough locked gold' - ) - }) - }) - }) - - describe('when the account is already a registered validator', () => { - beforeEach(async () => { - await registerValidator(group) - }) - - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.registerValidatorGroup(commission), - 'Already registered as validator' - ) - }) - }) - - describe('when the account is already a registered validator group', () => { - beforeEach(async () => { - await mockLockedGold.setAccountTotalLockedGold(group, groupLockedGoldRequirements.value) - await validators.registerValidatorGroup(commission) - }) - - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.registerValidatorGroup(commission), - 'Already registered as group' - ) - }) - }) - - describe('when the account is already a registered validator group', () => { - beforeEach(async () => { - await registerValidatorGroup(group) - }) - - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.registerValidatorGroup(commission), - 'Already registered as group' - ) - }) - }) - }) - - describe('#deregisterValidatorGroup', () => { - const index = 0 - const group = accounts[0] - let resp: any - describe('when the account has a registered validator group', () => { - beforeEach(async () => { - await registerValidatorGroup(group) - }) - describe('when the group has never had any members', () => { - beforeEach(async () => { - resp = await validators.deregisterValidatorGroup(index) - }) - - it('should mark the account as not a validator group', async () => { - assert.isFalse(await validators.isValidatorGroup(group)) - }) - - it('should remove the account from the list of validator groups', async () => { - assert.deepEqual(await validators.getRegisteredValidatorGroups(), []) - }) - - it('should reset account balance requirements', async () => { - const requirement = await validators.getAccountLockedGoldRequirement(group) - assertEqualBN(requirement, 0) - }) - - it('should emit the ValidatorGroupDeregistered event', async () => { - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ValidatorGroupDeregistered', - args: { - group, - }, - }) - }) - }) - - describe('when the group has had members', () => { - const validator = accounts[1] - beforeEach(async () => { - await registerValidator(validator) - await validators.affiliate(group, { from: validator }) - await validators.addFirstMember(validator, NULL_ADDRESS, NULL_ADDRESS) - }) - - describe('when the group no longer has members', () => { - beforeEach(async () => { - await validators.removeMember(validator) - }) - - describe('when it has been more than `groupLockedGoldRequirements.duration` since the validator was removed from the group', () => { - beforeEach(async () => { - await timeTravel(groupLockedGoldRequirements.duration.plus(1).toNumber(), web3) - resp = await validators.deregisterValidatorGroup(index) - }) - - it('should mark the account as not a validator group', async () => { - assert.isFalse(await validators.isValidatorGroup(group)) - }) - - it('should remove the account from the list of validator groups', async () => { - assert.deepEqual(await validators.getRegisteredValidatorGroups(), []) - }) - - it('should reset account balance requirements', async () => { - const requirement = await validators.getAccountLockedGoldRequirement(group) - assertEqualBN(requirement, 0) - }) - - it('should emit the ValidatorGroupDeregistered event', async () => { - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ValidatorGroupDeregistered', - args: { - group, - }, - }) - }) - }) - - describe('when it has been less than `groupLockedGoldRequirements.duration` since the validator was removed from the group', () => { - beforeEach(async () => { - await timeTravel(groupLockedGoldRequirements.duration.minus(1).toNumber(), web3) - }) - - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.deregisterValidatorGroup(index), - "Hasn't been empty for long enough" - ) - }) - }) - }) - - describe('when the group still has members', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.deregisterValidatorGroup(index), - 'Validator group not empty' - ) - }) - }) - }) - - it('should revert when the wrong index is provided', async () => { - await assertTransactionRevertWithReason( - validators.deregisterValidatorGroup(index + 1), - 'deleteElement: index out of range' - ) - }) - }) - - describe('when the account does not have a registered validator group', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.deregisterValidatorGroup(index), - 'Not a validator group' - ) - }) - }) - }) - - describe('#addMember', () => { - const group = accounts[0] - const validator = accounts[1] - let resp: any - describe('when account has a registered validator group', () => { - beforeEach(async () => { - await registerValidatorGroup(group) - }) - describe('when adding a validator affiliated with the group', () => { - let registrationEpoch: number - beforeEach(async () => { - await registerValidator(validator) - registrationEpoch = await currentEpochNumber(web3) - await validators.affiliate(group, { from: validator }) - }) - - describe('when the group meets the locked gold requirements', () => { - describe('when the validator meets the locked gold requirements', () => { - let additionEpoch: number - beforeEach(async () => { - resp = await validators.addFirstMember(validator, NULL_ADDRESS, NULL_ADDRESS) - additionEpoch = await currentEpochNumber(web3) - }) - - it('should add the member to the list of members', async () => { - const parsedGroup = parseValidatorGroupParams( - await validators.getValidatorGroup(group) - ) - assert.deepEqual(parsedGroup.members, [validator]) - }) - - it("should update the groups's size history", async () => { - const parsedGroup = parseValidatorGroupParams( - await validators.getValidatorGroup(group) - ) - assert.equal(parsedGroup.sizeHistory.length, 1) - assertEqualBN( - parsedGroup.sizeHistory[0], - (await web3.eth.getBlock('latest')).timestamp - ) - }) - - it("should update the member's membership history", async () => { - const expectedEntries = registrationEpoch === additionEpoch ? 1 : 2 - const membershipHistory = parseMembershipHistory( - await validators.getMembershipHistory(validator) - ) - assert.equal(membershipHistory.epochs.length, expectedEntries) - assertEqualBN(membershipHistory.epochs[expectedEntries - 1], additionEpoch) - assert.equal(membershipHistory.groups.length, expectedEntries) - assertSameAddress(membershipHistory.groups[expectedEntries - 1], group) - }) - - it('should mark the group as eligible', async () => { - assert.isTrue(await mockElection.isEligible(group)) - }) - - it('should emit the ValidatorGroupMemberAdded event', async () => { - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ValidatorGroupMemberAdded', - args: { - group, - validator, - }, - }) - }) - - describe('when the group has no room to add another member', () => { - beforeEach(async () => { - await validators.setMaxGroupSize(1) - await registerValidator(accounts[2]) - await validators.affiliate(group, { from: accounts[2] }) - }) - - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.addMember(accounts[2]), - 'group would exceed maximum size' - ) - }) - }) - - describe('when adding many validators affiliated with the group', () => { - it("should update the groups's size history and balance requirements", async () => { - const expectedSizeHistory = parseValidatorGroupParams( - await validators.getValidatorGroup(group) - ).sizeHistory - assert.equal(expectedSizeHistory.length, 1) - for (let i = 2; i < maxGroupSize.toNumber() + 1; i++) { - const numMembers = i - const validator1 = accounts[i] - await registerValidator(validator1) - await validators.affiliate(group, { from: validator1 }) - await mockLockedGold.setAccountTotalLockedGold( - group, - groupLockedGoldRequirements.value.times(numMembers) - ) - await validators.addMember(validator1) - expectedSizeHistory.push((await web3.eth.getBlock('latest')).timestamp) - const parsedGroup = parseValidatorGroupParams( - await validators.getValidatorGroup(group) - ) - assert.deepEqual( - parsedGroup.sizeHistory.map((x) => x.toString()), - expectedSizeHistory.map((x) => x.toString()) - ) - const requirement = await validators.getAccountLockedGoldRequirement(group) - assertEqualBN(requirement, groupLockedGoldRequirements.value.times(numMembers)) - } - }) - }) - }) - - describe('when the validator does not meet the locked gold requirements', () => { - beforeEach(async () => { - await mockLockedGold.setAccountTotalLockedGold( - validator, - validatorLockedGoldRequirements.value.minus(11) - ) - }) - - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.addFirstMember(validator, NULL_ADDRESS, NULL_ADDRESS), - 'Validator requirements not met' - ) - }) - }) - }) - - describe('when the group does not meet the locked gold requirements', () => { - describe('when the group does not have a member', () => { - beforeEach(async () => { - await mockLockedGold.setAccountTotalLockedGold( - group, - groupLockedGoldRequirements.value.minus(11) - ) - }) - - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.addFirstMember(validator, NULL_ADDRESS, NULL_ADDRESS), - 'Group requirements not met' - ) - }) - }) - - describe('when the group already has a member', () => { - const validator2 = accounts[2] - beforeEach(async () => { - await mockLockedGold.setAccountTotalLockedGold( - group, - groupLockedGoldRequirements.value.times(2).minus(11) - ) - await validators.addFirstMember(validator, NULL_ADDRESS, NULL_ADDRESS) - await registerValidator(validator2) - await validators.affiliate(group, { from: validator2 }) - }) - - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.addMember(validator2), - 'Group requirements not met' - ) - }) - }) - }) - }) - - describe('when adding a validator not affiliated with the group', () => { - beforeEach(async () => { - await registerValidator(validator) - }) - - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.addFirstMember(validator, NULL_ADDRESS, NULL_ADDRESS), - 'Not affiliated to group' - ) - }) - }) - }) - - describe('when the account does not have a registered validator group', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.addFirstMember(validator, NULL_ADDRESS, NULL_ADDRESS), - 'Not validator and group' - ) - }) - }) - - describe('when the validator is already a member of the group', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.addMember(validator), - 'Validator group empty' - ) - }) - }) - }) - - describe('#removeMember', () => { - const group = accounts[0] - const validator = accounts[1] - beforeEach(async () => { - await registerValidatorGroupWithMembers(group, [validator]) - }) - - it('should remove the member from the list of members', async () => { - await validators.removeMember(validator) - const parsedGroup = parseValidatorGroupParams(await validators.getValidatorGroup(group)) - assert.deepEqual(parsedGroup.members, []) - }) - - it("should update the member's membership history", async () => { - await validators.removeMember(validator) - const membershipHistory = parseMembershipHistory( - await validators.getMembershipHistory(validator) - ) - const expectedEpoch = await currentEpochNumber(web3) - - // Depending on test timing, we may or may not span an epoch boundary between registration - // and removal. - const numEntries = membershipHistory.epochs.length - assert.isTrue(numEntries === 1 || numEntries === 2) - assert.equal(membershipHistory.groups.length, numEntries) - if (numEntries === 1) { - assertEqualBN(membershipHistory.epochs[0], expectedEpoch) - assertSameAddress(membershipHistory.groups[0], NULL_ADDRESS) - } else { - assertEqualBN(membershipHistory.epochs[1], expectedEpoch) - assertSameAddress(membershipHistory.groups[1], NULL_ADDRESS) - } - const latestBlock = await web3.eth.getBlock('latest') - assert.equal(membershipHistory.lastRemovedFromGroupTimestamp, latestBlock.timestamp) - }) - - it("should update the group's size history", async () => { - await validators.removeMember(validator) - const parsedGroup = parseValidatorGroupParams(await validators.getValidatorGroup(group)) - assert.equal(parsedGroup.sizeHistory.length, 2) - assertEqualBN(parsedGroup.sizeHistory[1], (await web3.eth.getBlock('latest')).timestamp) - }) - - it('should emit the ValidatorGroupMemberRemoved event', async () => { - const resp = await validators.removeMember(validator) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ValidatorGroupMemberRemoved', - args: { - group, - validator, - }, - }) - }) - - describe('when the validator is the only member of the group', () => { - it('should mark the group ineligible', async () => { - await validators.removeMember(validator) - assert.isTrue(await mockElection.isIneligible(group)) - }) - }) - - it('should revert when the account is not a registered validator group', async () => { - await assertTransactionRevertWithReason( - validators.removeMember(validator, { from: accounts[2] }), - 'is not group and validator' - ) - }) - - it('should revert when the member is not a registered validator', async () => { - await assertTransactionRevertWithReason( - validators.removeMember(accounts[2]), - 'is not group and validator' - ) - }) - - describe('when the validator is not a member of the validator group', () => { - beforeEach(async () => { - await validators.deaffiliate({ from: validator }) - }) - - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.removeMember(validator), - 'Not affiliated to group' - ) - }) - }) - }) - - describe('#reorderMember', () => { - const group = accounts[0] - const validator1 = accounts[1] - const validator2 = accounts[2] - beforeEach(async () => { - await registerValidatorGroupWithMembers(group, [validator1, validator2]) - }) - - it('should reorder the list of group members', async () => { - await validators.reorderMember(validator2, validator1, NULL_ADDRESS) - const parsedGroup = parseValidatorGroupParams(await validators.getValidatorGroup(group)) - assert.deepEqual(parsedGroup.members, [validator2, validator1]) - }) - - it('should emit the ValidatorGroupMemberReordered event', async () => { - const resp = await validators.reorderMember(validator2, validator1, NULL_ADDRESS) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ValidatorGroupMemberReordered', - args: { - group, - validator: validator2, - }, - }) - }) - - it('should revert when the account is not a registered validator group', async () => { - await assertTransactionRevertWithReason( - validators.reorderMember(validator2, validator1, NULL_ADDRESS, { from: accounts[2] }), - 'Not a group' - ) - }) - - it('should revert when the member is not a registered validator', async () => { - await assertTransactionRevertWithReason( - validators.reorderMember(accounts[3], validator1, NULL_ADDRESS), - 'Not a validator' - ) - }) - - describe('when the validator is not a member of the validator group', () => { - beforeEach(async () => { - await validators.deaffiliate({ from: validator2 }) - }) - - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.reorderMember(validator2, validator1, NULL_ADDRESS), - 'Not a member of the group' - ) - }) - }) - }) - - describe('#setNextCommissionUpdate()', () => { - describe('when the commission is different', () => { - const newCommission = commission.plus(1) - const group = accounts[0] - - describe('when called by a registered validator group', () => { - let resp: any - - beforeEach(async () => { - await registerValidatorGroup(group) - resp = await validators.setNextCommissionUpdate(newCommission) - }) - - it('should NOT set the validator group commission', async () => { - const parsedGroup = parseValidatorGroupParams(await validators.getValidatorGroup(group)) - assertEqualBN(parsedGroup.commission, commission) - }) - - it('should set the validator group next commission', async () => { - const parsedGroup = parseValidatorGroupParams(await validators.getValidatorGroup(group)) - assertEqualBN(parsedGroup.nextCommission, newCommission) - }) - - it('should emit the ValidatorGroupCommissionUpdateQueued event', async () => { - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - const blockNumber = log.blockNumber - assertContainSubset(log, { - event: 'ValidatorGroupCommissionUpdateQueued', - args: { - group, - commission: newCommission, - activationBlock: commissionUpdateDelay.plus(blockNumber), - }, - }) - }) - }) - - describe('when the commission is the same', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.setNextCommissionUpdate(commission), - 'Not a validator group' - ) - }) - }) - - describe('when the commission is greater than one', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.setNextCommissionUpdate(fixed1.plus(1)), - 'Not a validator group' - ) - }) - }) - }) - }) - describe('#updateCommission()', () => { - const group = accounts[0] - const newCommission = commission.plus(1) - - beforeEach(async () => { - await registerValidatorGroup(group) - }) - - describe('when activationBlock has passed', () => { - let resp: any - - beforeEach(async () => { - await validators.setNextCommissionUpdate(newCommission) - await mineBlocks(commissionUpdateDelay.toNumber(), web3) - resp = await validators.updateCommission() - }) - - it('should set the validator group commission', async () => { - const parsedGroup = parseValidatorGroupParams(await validators.getValidatorGroup(group)) - assertEqualBN(parsedGroup.commission, newCommission) - }) - - it('should emit the ValidatorGroupCommissionUpdated event', async () => { - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ValidatorGroupCommissionUpdated', - args: { - group, - commission: newCommission, - }, - }) - }) - }) - - describe('when activationBlock has NOT passed', () => { - it('should revert', async () => { - await validators.setNextCommissionUpdate(newCommission) - await assertTransactionRevertWithReason( - validators.updateCommission(), - "Can't apply commission update yet" - ) - }) - }) - - describe('when NO Commission has been queued', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.updateCommission(), - 'No commission update queued' - ) - }) - }) - - describe('when try to apply an already applied Commission', () => { - it('should revert', async () => { - await validators.setNextCommissionUpdate(newCommission) - await mineBlocks(commissionUpdateDelay.toNumber(), web3) - await validators.updateCommission() - await assertTransactionRevertWithReason( - validators.updateCommission(), - 'No commission update queued' - ) - }) - }) - }) - - describe('#calculateEpochScore', () => { - describe('when uptime is in the interval [0, 1.0]', () => { - it('should calculate the score correctly', async () => { - // Compare expected and actual to 8 decimal places. - const uptime = new BigNumber(0.99) - const grace = await validators.downtimeGracePeriod() - assertEqualDpBN( - fromFixed(await validators.calculateEpochScore(toFixed(uptime))), - calculateScore(uptime, grace), - 8 - ) - assertEqualDpBN( - fromFixed(await validators.calculateEpochScore(new BigNumber(0))), - calculateScore(new BigNumber(0), grace), - 8 - ) - - assertEqualDpBN(fromFixed(await validators.calculateEpochScore(fixed1)), 1, 8) - }) - }) - - describe('when uptime > 1.0', () => { - const uptime = new BigNumber(1.01) - it('should revert', async () => { - await assertRevert(validators.calculateEpochScore(toFixed(uptime))) - }) - }) - }) - - describe('#calculateGroupEpochScore', () => { - describe('when all uptimes are in the interval [0, 1.0]', () => { - const testGroupUptimeCalculation = async (_uptimes) => { - const gracePeriod = await validators.downtimeGracePeriod() - const expected = _uptimes - .map((uptime) => new BigNumber(uptime)) - .map((uptime) => calculateScore(uptime, gracePeriod)) - .reduce((sum, n) => sum.plus(n)) - .div(_uptimes.length) - - it('should calculate the group score correctly', async () => { - assertEqualDpBN( - fromFixed(await validators.calculateGroupEpochScore(_uptimes.map(toFixed))), - expected, - 8 - ) - }) - } - - // 5 random uptimes between zero and one. - const uptimes = [0.969, 0.485, 0.456, 0.744, 0.257] - for (const count of [1, 3, 5]) { - it(`when there are ${count} validators in the group`, async () => { - await testGroupUptimeCalculation(uptimes.slice(0, count)) - }) - } - - it('when only zeros are provided', async () => { - await testGroupUptimeCalculation([0, 0, 0, 0]) - }) - - it('when there are zeros in the uptimes', async () => { - await testGroupUptimeCalculation([0.75, 0, 0.95]) - }) - - describe('when there are more than maxGroupSize uptimes', () => { - it('should revert', async () => { - await assertRevert( - validators.calculateGroupEpochScore([0.9, 0.9, 0.9, 0.9, 0.9, 0.9].map(toFixed)) - ) - }) - }) - }) - - describe('when no uptimes are provided', () => { - it('should revert', async () => { - await assertRevert(validators.calculateGroupEpochScore([])) - }) - }) - - describe('when uptimes are > 1.0', () => { - it('should revert', async () => { - await assertRevert(validators.calculateGroupEpochScore([0.95, 1.01, 0.99].map(toFixed))) - }) - }) - }) - - describe('#updateValidatorScoreFromSigner', () => { - const validator = accounts[0] - let grace: BigNumber - - beforeEach(async () => { - await registerValidator(validator) - grace = await validators.downtimeGracePeriod() - }) - - describe('when 0 <= uptime <= 1.0', () => { - const uptime = new BigNumber(0.99) - - let epochScore: BigNumber - let adjustmentSpeed: BigNumber - - beforeEach(async () => { - epochScore = calculateScore(uptime, grace) - adjustmentSpeed = fromFixed(validatorScoreParameters.adjustmentSpeed) - await validators.updateValidatorScoreFromSigner(validator, toFixed(uptime)) - }) - - it('should update the validator score', async () => { - const expectedScore = adjustmentSpeed.times(epochScore).decimalPlaces(12) - const parsedValidator = parseValidatorParams(await validators.getValidator(validator)) - assertEqualBN(parsedValidator.score, toFixed(expectedScore)) - }) - - describe('when the validator already has a non-zero score', () => { - beforeEach(async () => { - await validators.updateValidatorScoreFromSigner(validator, toFixed(uptime)) - }) - - it('should update the validator score', async () => { - let expectedScore = adjustmentSpeed.times(epochScore).decimalPlaces(12) - expectedScore = new BigNumber(1) - .minus(adjustmentSpeed) - .times(expectedScore) - .plus(expectedScore) - const parsedValidator = parseValidatorParams(await validators.getValidator(validator)) - assertEqualBN(parsedValidator.score, toFixed(expectedScore)) - }) - }) - }) - - describe('when uptime > 1.0', () => { - const uptime = 1.01 - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.updateValidatorScoreFromSigner(validator, toFixed(uptime)), - 'Uptime cannot be larger than one' - ) - }) - }) - }) - - describe('#updateMembershipHistory', () => { - const validator = accounts[0] - const groups = accounts.slice(1, -1) - let validatorRegistrationEpochNumber: number - beforeEach(async () => { - await registerValidator(validator) - validatorRegistrationEpochNumber = await currentEpochNumber(web3) - for (const group of groups) { - await registerValidatorGroup(group) - } - }) - - describe('when changing groups in the same epoch', () => { - it('should overwrite the previous entry', async () => { - const numTests = 10 - // We store an entry upon registering the validator. - const expectedMembershipHistoryGroups = [NULL_ADDRESS] - const expectedMembershipHistoryEpochs = [new BigNumber(validatorRegistrationEpochNumber)] - for (let i = 0; i < numTests; i++) { - await mineToNextEpoch(web3) - const epochNumber = await currentEpochNumber(web3) - let group = groups[0] - await validators.affiliate(group) - await validators.addFirstMember(validator, NULL_ADDRESS, NULL_ADDRESS, { - from: group, - }) - let membershipHistory = await validators.getMembershipHistory(validator) - expectedMembershipHistoryGroups.push(group) - expectedMembershipHistoryEpochs.push(new BigNumber(epochNumber)) - if (expectedMembershipHistoryGroups.length > membershipHistoryLength.toNumber()) { - expectedMembershipHistoryGroups.shift() - expectedMembershipHistoryEpochs.shift() - } - assertEqualBNArray(membershipHistory[0], expectedMembershipHistoryEpochs) - assert.deepEqual(membershipHistory[1], expectedMembershipHistoryGroups) - - group = groups[1] - await validators.affiliate(group) - await validators.addFirstMember(validator, NULL_ADDRESS, NULL_ADDRESS, { - from: group, - }) - membershipHistory = await validators.getMembershipHistory(validator) - expectedMembershipHistoryGroups[expectedMembershipHistoryGroups.length - 1] = group - assertEqualBNArray(membershipHistory[0], expectedMembershipHistoryEpochs) - assert.deepEqual(membershipHistory[1], expectedMembershipHistoryGroups) - } - }) - }) - - describe('when changing groups more times than membership history length', () => { - it('should always store the most recent memberships', async () => { - // We store an entry upon registering the validator. - const expectedMembershipHistoryGroups = [NULL_ADDRESS] - const expectedMembershipHistoryEpochs = [new BigNumber(validatorRegistrationEpochNumber)] - for (let i = 0; i < membershipHistoryLength.plus(1).toNumber(); i++) { - await mineToNextEpoch(web3) - const epochNumber = await currentEpochNumber(web3) - await validators.affiliate(groups[i]) - await validators.addFirstMember(validator, NULL_ADDRESS, NULL_ADDRESS, { - from: groups[i], - }) - expectedMembershipHistoryGroups.push(groups[i]) - expectedMembershipHistoryEpochs.push(new BigNumber(epochNumber)) - if (expectedMembershipHistoryGroups.length > membershipHistoryLength.toNumber()) { - expectedMembershipHistoryGroups.shift() - expectedMembershipHistoryEpochs.shift() - } - const membershipHistory = await validators.getMembershipHistory(validator) - assertEqualBNArray(membershipHistory[0], expectedMembershipHistoryEpochs) - assert.deepEqual(membershipHistory[1], expectedMembershipHistoryGroups) - } - }) - }) - }) - - describe('#getMembershipInLastEpoch', () => { - const validator = accounts[0] - const groups = accounts.slice(1, -1) - beforeEach(async () => { - await registerValidator(validator) - for (const group of groups) { - await registerValidatorGroup(group) - } - }) - - describe('when changing groups more times than membership history length', () => { - it('should always return the correct membership for the last epoch', async () => { - for (let i = 0; i < membershipHistoryLength.plus(1).toNumber(); i++) { - await mineToNextEpoch(web3) - - await validators.affiliate(groups[i]) - await validators.addFirstMember(validator, NULL_ADDRESS, NULL_ADDRESS, { - from: groups[i], - }) - - if (i === 0) { - assert.equal(await validators.getMembershipInLastEpoch(validator), NULL_ADDRESS) - } else { - assert.equal(await validators.getMembershipInLastEpoch(validator), groups[i - 1]) - } - } - }) - }) - }) - - describe('#getEpochSize', () => { - it('should always return 100', async () => { - assertEqualBN(await validators.getEpochSize(), 100) - }) - }) - - describe('#getAccountLockedGoldRequirement', () => { - describe('when a validator group has added members', () => { - const group = accounts[0] - const numMembers = 5 - let actualRequirements: BigNumber[] - beforeEach(async () => { - actualRequirements = [] - await registerValidatorGroup(group) - for (let i = 1; i < numMembers + 1; i++) { - const validator = accounts[i] - await registerValidator(validator) - await validators.affiliate(group, { from: validator }) - await mockLockedGold.setAccountTotalLockedGold( - group, - groupLockedGoldRequirements.value.times(i) - ) - if (i === 1) { - await validators.addFirstMember(validator, NULL_ADDRESS, NULL_ADDRESS) - } else { - await validators.addMember(validator) - } - actualRequirements.push(await validators.getAccountLockedGoldRequirement(group)) - } - }) - - it('should increase the requirement with each added member', async () => { - for (let i = 0; i < numMembers; i++) { - assertEqualBN(actualRequirements[i], groupLockedGoldRequirements.value.times(i + 1)) - } - }) - - describe('when a validator group is removing members', () => { - let removalTimestamps: number[] - beforeEach(async () => { - removalTimestamps = [] - for (let i = 1; i < numMembers + 1; i++) { - const validator = accounts[i] - await validators.removeMember(validator) - removalTimestamps.push((await web3.eth.getBlock('latest')).timestamp) - // Space things out. - await timeTravel(47, web3) - } - }) - - it('should decrease the requirement `duration`+1 seconds after removal', async () => { - for (let i = 0; i < numMembers; i++) { - assertEqualBN( - await validators.getAccountLockedGoldRequirement(group), - groupLockedGoldRequirements.value.times(numMembers - i) - ) - const removalTimestamp = removalTimestamps[i] - const requirementExpiry = groupLockedGoldRequirements.duration.plus(removalTimestamp) - const currentTimestamp = (await web3.eth.getBlock('latest')).timestamp - await timeTravel(requirementExpiry.minus(currentTimestamp).plus(1).toNumber(), web3) - } - }) - }) - }) - }) - - describe('#distributeEpochPaymentsFromSigner', () => { - const validator = accounts[0] - const group = accounts[1] - const delegatee = accounts[2] - const delegatedFraction = toFixed(0.1) - - const maxPayment = new BigNumber(20122394876) - let mockStableToken: MockStableTokenInstance - beforeEach(async () => { - await registerValidatorGroupWithMembers(group, [validator]) - mockStableToken = await MockStableToken.new() - await registry.setAddressFor(CeloContractName.StableToken, mockStableToken.address) - // Fast-forward to the next epoch, so that the getMembershipInLastEpoch(validator) == group - await mineToNextEpoch(web3) - await mockLockedGold.addSlasher(accounts[2]) - - await accountsInstance.setPaymentDelegation(delegatee, delegatedFraction) - }) - - describe('when the validator score is non-zero', () => { - let ret: BigNumber - let expectedScore: BigNumber - let expectedTotalPayment: BigNumber - let expectedGroupPayment: BigNumber - let expectedValidatorPayment: BigNumber - let expectedDelegatedPayment: BigNumber - - beforeEach(async () => { - const uptime = new BigNumber(0.99) - const adjustmentSpeed = fromFixed(validatorScoreParameters.adjustmentSpeed) - - expectedScore = adjustmentSpeed.times( - calculateScore(new BigNumber(0.99), await validators.downtimeGracePeriod()) - ) - expectedTotalPayment = expectedScore.times(maxPayment).dp(0, BigNumber.ROUND_FLOOR) - expectedGroupPayment = expectedTotalPayment - .times(fromFixed(commission)) - .dp(0, BigNumber.ROUND_FLOOR) - const remainingPayment = expectedTotalPayment.minus(expectedGroupPayment) - expectedDelegatedPayment = remainingPayment - .times(fromFixed(delegatedFraction)) - .dp(0, BigNumber.ROUND_FLOOR) - expectedValidatorPayment = remainingPayment.minus(expectedDelegatedPayment) - - await validators.updateValidatorScoreFromSigner(validator, toFixed(uptime)) - }) - - describe('when the validator and group meet the balance requirements', () => { - beforeEach(async () => { - ret = await validators.distributeEpochPaymentsFromSigner.call(validator, maxPayment) - await validators.distributeEpochPaymentsFromSigner(validator, maxPayment) - }) - - it('should pay the validator', async () => { - assertEqualBN(await mockStableToken.balanceOf(validator), expectedValidatorPayment) - }) - - it('should pay the group', async () => { - assertEqualBN(await mockStableToken.balanceOf(group), expectedGroupPayment) - }) - - it('should pay the delegatee', async () => { - assertEqualBN(await mockStableToken.balanceOf(delegatee), expectedDelegatedPayment) - }) - - it('should return the expected total payment', async () => { - assertEqualBN(ret, expectedTotalPayment) - }) - }) - - describe('when the validator and group meet the balance requirements and no payment is delegated', async () => { - beforeEach(async () => { - expectedDelegatedPayment = new BigNumber(0) - expectedValidatorPayment = expectedTotalPayment.minus(expectedGroupPayment) - - await accountsInstance.deletePaymentDelegation() - - ret = await validators.distributeEpochPaymentsFromSigner.call(validator, maxPayment) - await validators.distributeEpochPaymentsFromSigner(validator, maxPayment) - }) - - it('should pay the validator', async () => { - assertEqualBN(await mockStableToken.balanceOf(validator), expectedValidatorPayment) - }) - - it('should pay the group', async () => { - assertEqualBN(await mockStableToken.balanceOf(group), expectedGroupPayment) - }) - - it('should return the expected total payment', async () => { - assertEqualBN(ret, expectedTotalPayment) - }) - }) - - describe('when slashing multiplier is halved', () => { - let halfExpectedTotalPayment: BigNumber - let halfExpectedGroupPayment: BigNumber - let halfExpectedValidatorPayment: BigNumber - let halfExpectedDelegatedPayment: BigNumber - - beforeEach(async () => { - halfExpectedTotalPayment = expectedScore - .times(maxPayment) - .div(2) - .dp(0, BigNumber.ROUND_FLOOR) - halfExpectedGroupPayment = halfExpectedTotalPayment - .times(fromFixed(commission)) - .dp(0, BigNumber.ROUND_FLOOR) - const remainingPayment = halfExpectedTotalPayment.minus(halfExpectedGroupPayment) - halfExpectedDelegatedPayment = remainingPayment - .times(fromFixed(delegatedFraction)) - .dp(0, BigNumber.ROUND_FLOOR) - halfExpectedValidatorPayment = remainingPayment.minus(halfExpectedDelegatedPayment) - - await validators.halveSlashingMultiplier(group, { from: accounts[2] }) - ret = await validators.distributeEpochPaymentsFromSigner.call(validator, maxPayment) - await validators.distributeEpochPaymentsFromSigner(validator, maxPayment) - }) - - it('should pay the validator only half', async () => { - assertEqualBN(await mockStableToken.balanceOf(validator), halfExpectedValidatorPayment) - }) - - it('should pay the group only half', async () => { - assertEqualBN(await mockStableToken.balanceOf(group), halfExpectedGroupPayment) - }) - - it('should pay the delegatee only half', async () => { - assertEqualBN(await mockStableToken.balanceOf(delegatee), halfExpectedDelegatedPayment) - }) - - it('should return the expected total payment', async () => { - assertEqualBN(ret, halfExpectedTotalPayment) - }) - }) - - describe('when the validator does not meet the balance requirements', () => { - beforeEach(async () => { - await mockLockedGold.setAccountTotalLockedGold( - validator, - validatorLockedGoldRequirements.value.minus(11) - ) - ret = await validators.distributeEpochPaymentsFromSigner.call(validator, maxPayment) - await validators.distributeEpochPaymentsFromSigner(validator, maxPayment) - }) - - it('should not pay the validator', async () => { - assertEqualBN(await mockStableToken.balanceOf(validator), 0) - }) - - it('should not pay the group', async () => { - assertEqualBN(await mockStableToken.balanceOf(group), 0) - }) - - it('should not pay the delegatee', async () => { - assertEqualBN(await mockStableToken.balanceOf(delegatee), 0) - }) - - it('should return zero', async () => { - assertEqualBN(ret, 0) - }) - }) - - describe('when the group does not meet the balance requirements', () => { - beforeEach(async () => { - await mockLockedGold.setAccountTotalLockedGold( - group, - groupLockedGoldRequirements.value.minus(11) - ) - ret = await validators.distributeEpochPaymentsFromSigner.call(validator, maxPayment) - await validators.distributeEpochPaymentsFromSigner(validator, maxPayment) - }) - - it('should not pay the validator', async () => { - assertEqualBN(await mockStableToken.balanceOf(validator), 0) - }) - - it('should not pay the group', async () => { - assertEqualBN(await mockStableToken.balanceOf(group), 0) - }) - - it('should not pay the delegatee', async () => { - assertEqualBN(await mockStableToken.balanceOf(delegatee), 0) - }) - - it('should return zero', async () => { - assertEqualBN(ret, 0) - }) - }) - }) - }) - - describe('#forceDeaffiliateIfValidator', () => { - const validator = accounts[0] - const group = accounts[1] - - beforeEach(async () => { - await registerValidator(validator) - await registerValidatorGroup(group) - await validators.affiliate(group) - await mockLockedGold.addSlasher(accounts[2]) - }) - - describe('when the sender is one of the whitelisted slashing addresses', () => { - it('should succeed when the account is manually added', async () => { - await validators.forceDeaffiliateIfValidator(validator, { from: accounts[2] }) - const parsedValidator = parseValidatorParams(await validators.getValidator(validator)) - assert.equal(parsedValidator.affiliation, NULL_ADDRESS) - }) - }) - - describe('when the sender is not an approved address', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - validators.forceDeaffiliateIfValidator(validator), - 'Only registered slasher can call' - ) - }) - }) - }) - - describe('#groupMembershipInEpoch', () => { - const validator = accounts[0] - const groups = accounts.slice(1, -1) - const gapSize = 3 - // Multiple of gapSize - const totalEpochs = 24 - // Stored index on chain - let contractIndex = 0 - - describe('when the validator is added to different groups with gaps in between epochs', () => { - let epochs = [] - - beforeEach(async () => { - // epochs stores [epochNumber, group] of the corresponding i + 1 indexed entry on chain - // i + 1 because registering validators adds a dummy null address as the first entry - epochs = [] - await registerValidator(validator) - contractIndex = 1 - for (const group of groups) { - await registerValidatorGroup(group) - } - // Start at 1 since we can't start with deaffiliate - for (let i = 1; i < totalEpochs; i++) { - await mineToNextEpoch(web3) - - const epochNumber = await currentEpochNumber(web3) - if (i % gapSize === 0) { - const group = - i % (gapSize * gapSize) !== 0 - ? groups[Math.floor(i / gapSize) % groups.length] - : NULL_ADDRESS - contractIndex += 1 - // Current epochNumber is 1 greater since we just called `mineBlocks` - epochs.push([epochNumber + 1, group]) - // deaffiliate every gapSize^2 entry - if (i % (gapSize * gapSize) !== 0) { - await validators.affiliate(group) - await validators.addFirstMember(validator, NULL_ADDRESS, NULL_ADDRESS, { - from: group, - }) - } else { - await validators.deaffiliate() - } - } - } - }) - - it('should correctly get the group address for exact epoch numbers', async () => { - for (let i = 0; i < epochs.length; i++) { - const group = epochs[i][1] - if (epochs.length - i <= membershipHistoryLength.toNumber()) { - assert.equal( - await validators.groupMembershipInEpoch(validator, epochs[i][0], 1 + i), - group - ) - } else { - await assertRevert(validators.groupMembershipInEpoch(validator, epochs[i][0], 1 + i)) - } - } - }) - - describe('when called with various malformed inputs', () => { - it('should revert when epochNumber at given index is greater than provided epochNumber', async () => { - await assertRevert( - validators.groupMembershipInEpoch( - validator, - epochs[epochs.length - 2][0], - contractIndex - ) - ) - }) - - it("should revert when epochNumber fits into a different index's bucket", async () => { - await assertRevert( - validators.groupMembershipInEpoch( - validator, - epochs[epochs.length - 1][0], - contractIndex - 2 - ) - ) - }) - - it("should revert when epochNumber is greater than the chain's current epochNumber", async () => { - const epochNumber = await currentEpochNumber(web3) - await assertRevert( - validators.groupMembershipInEpoch(validator, epochNumber + 1, contractIndex) - ) - }) - - it('should revert when provided index is greater than greatest index on chain', async () => { - const epochNumber = await currentEpochNumber(web3) - await assertRevert( - validators.groupMembershipInEpoch(validator, epochNumber, contractIndex + 1) - ) - }) - - it('should revert when provided index is less than `tail` index on chain', async () => { - await assertRevert( - validators.groupMembershipInEpoch( - validator, - epochs[epochs.length - membershipHistoryLength.toNumber() - 1][0], - contractIndex - membershipHistoryLength.toNumber() - ) - ) - }) - }) - }) - }) - - describe('#halveSlashingMultiplier', async () => { - const group = accounts[1] - - beforeEach(async () => { - await registerValidatorGroup(group) - }) - - describe('when run from an approved address', async () => { - beforeEach(async () => { - await mockLockedGold.addSlasher(accounts[2]) - }) - - it('should halve the slashing multiplier of a group', async () => { - let multiplier = 1.0 - for (let i = 0; i < 10; i++) { - await validators.halveSlashingMultiplier(group, { from: accounts[2] }) - multiplier /= 2 - const parsedGroup = parseValidatorGroupParams(await validators.getValidatorGroup(group)) - assertEqualBN(parsedGroup.slashingMultiplier, toFixed(multiplier)) - } - }) - - it('should update `lastSlashed timestamp', async () => { - let parsedGroup = parseValidatorGroupParams(await validators.getValidatorGroup(group)) - const initialTimestamp = parsedGroup.lastSlashed - await validators.halveSlashingMultiplier(group, { from: accounts[2] }) - parsedGroup = parseValidatorGroupParams(await validators.getValidatorGroup(group)) - assert(parsedGroup.lastSlashed > initialTimestamp) - }) - - it('should revert when called by non-slasher', async () => { - await assertTransactionRevertWithReason( - validators.halveSlashingMultiplier(group, { from: accounts[0] }), - 'Only registered slasher can call' - ) - }) - }) - }) - - describe('#resetSlashingMultiplier', async () => { - const validator = accounts[0] - const group = accounts[1] - - beforeEach(async () => { - await registerValidator(validator) - await registerValidatorGroup(group) - await validators.affiliate(group) - await mockLockedGold.addSlasher(accounts[2]) - await validators.halveSlashingMultiplier(group, { from: accounts[2] }) - const parsedGroup = parseValidatorGroupParams(await validators.getValidatorGroup(group)) - assertEqualBN(parsedGroup.slashingMultiplier, toFixed(0.5)) - }) - - describe('when the slashing multiplier is reset after reset period', async () => { - it('should return to default 1.0', async () => { - await timeTravel(slashingMultiplierResetPeriod, web3) - await validators.resetSlashingMultiplier({ from: group }) - const parsedGroup = parseValidatorGroupParams(await validators.getValidatorGroup(group)) - assertEqualBN(parsedGroup.slashingMultiplier, toFixed(1)) - }) - }) - - describe('when the slashing multiplier is reset before reset period', async () => { - it('should revert', async () => { - await timeTravel(slashingMultiplierResetPeriod - 10, web3) - await assertTransactionRevertWithReason( - validators.resetSlashingMultiplier({ from: group }), - '`resetSlashingMultiplier` called before resetPeriod expired' - ) - }) - }) - - describe('when the slashing reset period is changed', async () => { - it('should be read properly', async () => { - const newPeriod = 60 * 60 * 24 * 10 // 10 days - await validators.setSlashingMultiplierResetPeriod(newPeriod) - await timeTravel(newPeriod, web3) - await validators.resetSlashingMultiplier({ from: group }) - const parsedGroup = parseValidatorGroupParams(await validators.getValidatorGroup(group)) - assertEqualBN(parsedGroup.slashingMultiplier, toFixed(1)) - }) - }) - }) -}) diff --git a/packages/protocol/test/governance/voting/election.ts b/packages/protocol/test/governance/voting/election.ts deleted file mode 100644 index 448071bbf..000000000 --- a/packages/protocol/test/governance/voting/election.ts +++ /dev/null @@ -1,2580 +0,0 @@ -import { NULL_ADDRESS } from '@celo/base/lib/address' -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { - assertAlmostEqualBN, - assertContainSubset, - assertEqualBN, - assertRevert, - assertTransactionRevertWithReason, - mineBlocks, -} from '@celo/protocol/lib/test-utils' -import { normalizeAddressWith0x } from '@celo/utils/lib/address' -import { fixed1, toFixed } from '@celo/utils/lib/fixidity' -import BigNumber from 'bignumber.js' -import { - AccountsContract, - AccountsInstance, - ElectionTestContract, - ElectionTestInstance, - FreezerContract, - FreezerInstance, - MockLockedGoldContract, - MockLockedGoldInstance, - MockRandomContract, - MockRandomInstance, - MockValidatorsContract, - MockValidatorsInstance, - RegistryContract, - RegistryInstance, -} from 'types' - -const Accounts: AccountsContract = artifacts.require('Accounts') -const ElectionTest: ElectionTestContract = artifacts.require('ElectionTest') -const Freezer: FreezerContract = artifacts.require('Freezer') -const MockLockedGold: MockLockedGoldContract = artifacts.require('MockLockedGold') -const MockValidators: MockValidatorsContract = artifacts.require('MockValidators') -const MockRandom: MockRandomContract = artifacts.require('MockRandom') -const Registry: RegistryContract = artifacts.require('Registry') - -// @ts-ignore -// TODO(mcortesi): Use BN -ElectionTest.numberFormat = 'BigNumber' -// @ts-ignoree -MockLockedGold.numberFormat = 'BigNumber' - -// Hard coded in ganache. -const EPOCH = 100 - -contract('Election', (accounts: string[]) => { - let accountsInstance: AccountsInstance - let election: ElectionTestInstance - let freezer: FreezerInstance - let registry: RegistryInstance - let mockLockedGold: MockLockedGoldInstance - let mockValidators: MockValidatorsInstance - - const nonOwner = accounts[1] - const electableValidators = { - min: new BigNumber(4), - max: new BigNumber(6), - } - const maxNumGroupsVotedFor = new BigNumber(3) - const electabilityThreshold = toFixed(1 / 100) - - beforeEach(async () => { - accountsInstance = await Accounts.new(true) - await Promise.all(accounts.map((account) => accountsInstance.createAccount({ from: account }))) - election = await ElectionTest.new() - freezer = await Freezer.new(true) - mockLockedGold = await MockLockedGold.new() - mockValidators = await MockValidators.new() - registry = await Registry.new(true) - await registry.setAddressFor(CeloContractName.Accounts, accountsInstance.address) - await registry.setAddressFor(CeloContractName.Freezer, freezer.address) - await registry.setAddressFor(CeloContractName.LockedGold, mockLockedGold.address) - await registry.setAddressFor(CeloContractName.Validators, mockValidators.address) - await election.initialize( - registry.address, - electableValidators.min, - electableValidators.max, - maxNumGroupsVotedFor, - electabilityThreshold - ) - }) - - async function setupGroupAndVote( - newGroup: string, - oldGroup: string, - members: string[], - vote = true - ) { - await mockValidators.setMembers(newGroup, members) - await registry.setAddressFor(CeloContractName.Validators, accounts[0]) - await election.markGroupEligible(newGroup, oldGroup, NULL_ADDRESS) - await registry.setAddressFor(CeloContractName.Validators, mockValidators.address) - if (vote) { - await election.vote(newGroup, 1, oldGroup, NULL_ADDRESS) - } - } - - describe('#initialize()', () => { - it('should have set the owner', async () => { - const owner: string = await election.owner() - assert.equal(owner, accounts[0]) - }) - - it('should have set electableValidators', async () => { - const [min, max] = await election.getElectableValidators() - assertEqualBN(min, electableValidators.min) - assertEqualBN(max, electableValidators.max) - }) - - it('should have set maxNumGroupsVotedFor', async () => { - const actualMaxNumGroupsVotedFor = await election.maxNumGroupsVotedFor() - assertEqualBN(actualMaxNumGroupsVotedFor, maxNumGroupsVotedFor) - }) - - it('should have set electabilityThreshold', async () => { - const actualElectabilityThreshold = await election.getElectabilityThreshold() - assertEqualBN(actualElectabilityThreshold, electabilityThreshold) - }) - - it('should not be callable again', async () => { - await assertTransactionRevertWithReason( - election.initialize( - registry.address, - electableValidators.min, - electableValidators.max, - maxNumGroupsVotedFor, - electabilityThreshold - ), - 'contract already initialized' - ) - }) - }) - - describe('#setElectabilityThreshold', () => { - it('should set the electability threshold', async () => { - const threshold = toFixed(1 / 10) - await election.setElectabilityThreshold(threshold) - const result = await election.getElectabilityThreshold() - assertEqualBN(result, threshold) - }) - - it('should revert when the threshold is larger than 100%', async () => { - const threshold = toFixed(new BigNumber('2')) - await assertTransactionRevertWithReason( - election.setElectabilityThreshold(threshold), - 'Electability threshold must be lower than 100%' - ) - }) - }) - - describe('#setElectableValidators', () => { - const newElectableValidators = { - min: electableValidators.min.plus(1), - max: electableValidators.max.plus(1), - } - - it('should set the minimum electable valdiators', async () => { - await election.setElectableValidators(newElectableValidators.min, newElectableValidators.max) - const [min, max] = await election.getElectableValidators() - assertEqualBN(min, newElectableValidators.min) - assertEqualBN(max, newElectableValidators.max) - }) - - it('should emit the ElectableValidatorsSet event', async () => { - const resp = await election.setElectableValidators( - newElectableValidators.min, - newElectableValidators.max - ) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ElectableValidatorsSet', - args: { - min: newElectableValidators.min, - max: newElectableValidators.max, - }, - }) - }) - - it('should revert when the minElectableValidators is zero', async () => { - await assertTransactionRevertWithReason( - election.setElectableValidators(0, newElectableValidators.max), - 'Minimum electable validators cannot be zero' - ) - }) - - it('should revert when the min is greater than max', async () => { - await assertTransactionRevertWithReason( - election.setElectableValidators( - newElectableValidators.max.plus(1), - newElectableValidators.max - ), - 'Maximum electable validators cannot be smaller than minimum' - ) - }) - - it('should revert when the values are unchanged', async () => { - await assertTransactionRevertWithReason( - election.setElectableValidators(electableValidators.min, electableValidators.max), - 'Electable validators not changed' - ) - }) - - it('should revert when called by anyone other than the owner', async () => { - await assertTransactionRevertWithReason( - election.setElectableValidators(newElectableValidators.min, newElectableValidators.max, { - from: nonOwner, - }), - 'Ownable: caller is not the owner' - ) - }) - }) - - describe('#setMaxNumGroupsVotedFor', () => { - const newMaxNumGroupsVotedFor = maxNumGroupsVotedFor.plus(1) - it('should set the max electable validators', async () => { - await election.setMaxNumGroupsVotedFor(newMaxNumGroupsVotedFor) - assertEqualBN(await election.maxNumGroupsVotedFor(), newMaxNumGroupsVotedFor) - }) - - it('should emit the MaxNumGroupsVotedForSet event', async () => { - const resp = await election.setMaxNumGroupsVotedFor(newMaxNumGroupsVotedFor) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'MaxNumGroupsVotedForSet', - args: { - maxNumGroupsVotedFor: new BigNumber(newMaxNumGroupsVotedFor), - }, - }) - }) - - it('should revert when the maxNumGroupsVotedFor is unchanged', async () => { - await assertTransactionRevertWithReason( - election.setMaxNumGroupsVotedFor(maxNumGroupsVotedFor), - 'Max groups voted for not changed' - ) - }) - - it('should revert when called by anyone other than the owner', async () => { - await assertTransactionRevertWithReason( - election.setMaxNumGroupsVotedFor(newMaxNumGroupsVotedFor, { from: nonOwner }), - 'Ownable: caller is not the owner' - ) - }) - }) - - describe('#setAllowedToVoteOverMaxNumberOfGroups', () => { - it('should set Allowed To Vote Over Max Number Of Groups', async () => { - await election.setAllowedToVoteOverMaxNumberOfGroups(true) - assert.equal(await election.allowedToVoteOverMaxNumberOfGroups(accounts[0]), true) - }) - - it('should revert when vote over max number of groups set to true', async () => { - await mockValidators.setValidator(accounts[0]) - await assertTransactionRevertWithReason( - election.setAllowedToVoteOverMaxNumberOfGroups(true), - 'Validators cannot vote for more than max number of groups' - ) - }) - - it('should revert when vote over max number of groups set to true', async () => { - await mockValidators.setValidatorGroup(accounts[0]) - await assertTransactionRevertWithReason( - election.setAllowedToVoteOverMaxNumberOfGroups(true), - 'Validator groups cannot vote for more than max number of groups' - ) - }) - - it('should emit the AllowedToVoteOverMaxNumberOfGroups event', async () => { - const resp = await election.setAllowedToVoteOverMaxNumberOfGroups(true) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'AllowedToVoteOverMaxNumberOfGroups', - args: { - account: accounts[0], - flag: true, - }, - }) - }) - - describe('When AllowedToVoteOverMaxNumberOfGroups on', () => { - beforeEach(async () => { - await election.setAllowedToVoteOverMaxNumberOfGroups(true) - }) - - it('should turn AllowedToVoteOverMaxNumberOfGroups off', async () => { - await election.setAllowedToVoteOverMaxNumberOfGroups(false) - assert.equal(await election.allowedToVoteOverMaxNumberOfGroups(accounts[0]), false) - }) - - it('should emit the AllowedToVoteOverMaxNumberOfGroups event', async () => { - const resp = await election.setAllowedToVoteOverMaxNumberOfGroups(false) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'AllowedToVoteOverMaxNumberOfGroups', - args: { - account: accounts[0], - flag: false, - }, - }) - }) - }) - }) - - describe('#markGroupEligible', () => { - const group = accounts[1] - describe('when called by the registered validators contract', () => { - beforeEach(async () => { - await registry.setAddressFor(CeloContractName.Validators, accounts[0]) - }) - - describe('when the group has no votes', () => { - let resp: any - beforeEach(async () => { - resp = await election.markGroupEligible(group, NULL_ADDRESS, NULL_ADDRESS) - }) - - it('should add the group to the list of eligible groups', async () => { - assert.deepEqual(await election.getEligibleValidatorGroups(), [group]) - }) - - it('should emit the ValidatorGroupMarkedEligible event', async () => { - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ValidatorGroupMarkedEligible', - args: { - group, - }, - }) - }) - - describe('when the group has already been marked eligible', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - election.markGroupEligible(group, NULL_ADDRESS, NULL_ADDRESS), - 'invalid key' - ) - }) - }) - }) - }) - - describe('not called by the registered validators contract', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - election.markGroupEligible(group, NULL_ADDRESS, NULL_ADDRESS), - 'only registered contract' - ) - }) - }) - }) - - describe('#markGroupIneligible', () => { - const group = accounts[1] - describe('when the group is eligible', () => { - beforeEach(async () => { - await mockValidators.setMembers(group, [accounts[9]]) - await registry.setAddressFor(CeloContractName.Validators, accounts[0]) - await election.markGroupEligible(group, NULL_ADDRESS, NULL_ADDRESS) - await registry.setAddressFor(CeloContractName.Validators, mockValidators.address) - }) - - describe('when called by the registered Validators contract', () => { - let resp: any - beforeEach(async () => { - await registry.setAddressFor(CeloContractName.Validators, accounts[0]) - resp = await election.markGroupIneligible(group) - }) - - it('should remove the group from the list of eligible groups', async () => { - assert.deepEqual(await election.getEligibleValidatorGroups(), []) - }) - - it('should emit the ValidatorGroupMarkedIneligible event', async () => { - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ValidatorGroupMarkedIneligible', - args: { - group, - }, - }) - }) - }) - - describe('when not called by the registered Validators contract', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - election.markGroupIneligible(group), - 'only registered contract' - ) - }) - }) - }) - - describe('when the group is ineligible', () => { - describe('when called by the registered Validators contract', () => { - beforeEach(async () => { - await registry.setAddressFor(CeloContractName.Validators, accounts[0]) - }) - - it('should revert', async () => { - await assertTransactionRevertWithReason( - election.markGroupIneligible(group), - 'key not in list' - ) - }) - }) - }) - }) - - describe('#vote', () => { - const voter = accounts[0] - const group = accounts[1] - const value = new BigNumber(1000) - describe('when the group is eligible', () => { - beforeEach(async () => { - await mockValidators.setMembers(group, [accounts[9]]) - await registry.setAddressFor(CeloContractName.Validators, accounts[0]) - await election.markGroupEligible(group, NULL_ADDRESS, NULL_ADDRESS) - await registry.setAddressFor(CeloContractName.Validators, mockValidators.address) - }) - - describe('when the group can receive votes', () => { - beforeEach(async () => { - await mockLockedGold.setTotalLockedGold(value) - await mockValidators.setNumRegisteredValidators(1) - }) - - describe('when the voter can vote for an additional group', () => { - describe('when the voter has sufficient non-voting balance', () => { - beforeEach(async () => { - await mockLockedGold.incrementNonvotingAccountBalance(voter, value) - }) - - describe('when the voter has not already voted for this group', () => { - let resp: any - beforeEach(async () => { - resp = await election.vote(group, value, NULL_ADDRESS, NULL_ADDRESS) - }) - - it('should add the group to the list of groups the account has voted for', async () => { - assert.deepEqual(await election.getGroupsVotedForByAccount(voter), [group]) - }) - - it("should increment the account's pending votes for the group", async () => { - assertEqualBN(await election.getPendingVotesForGroupByAccount(group, voter), value) - }) - - it("should increment the account's total votes for the group", async () => { - assertEqualBN(await election.getTotalVotesForGroupByAccount(group, voter), value) - }) - - it("should increment the account's total votes", async () => { - assertEqualBN(await election.getTotalVotesByAccount(voter), value) - }) - - it('should increment the total votes for the group', async () => { - assertEqualBN(await election.getTotalVotesForGroup(group), value) - }) - - it('should increment the total votes', async () => { - assertEqualBN(await election.getTotalVotes(), value) - }) - - it("should decrement the account's nonvoting locked gold balance", async () => { - assertEqualBN(await mockLockedGold.nonvotingAccountBalance(voter), 0) - }) - - it('should emit the ValidatorGroupVoteCast event', async () => { - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ValidatorGroupVoteCast', - args: { - account: voter, - group, - value: new BigNumber(value), - }, - }) - }) - - describe('when the voter has already voted for this group', () => { - let response: any - beforeEach(async () => { - await mockLockedGold.incrementNonvotingAccountBalance(voter, value) - response = await election.vote(group, value, NULL_ADDRESS, NULL_ADDRESS) - }) - - it('should not change the list of groups the account has voted for', async () => { - assert.deepEqual(await election.getGroupsVotedForByAccount(voter), [group]) - }) - - it("should increment the account's pending votes for the group", async () => { - assertEqualBN( - await election.getPendingVotesForGroupByAccount(group, voter), - value.times(2) - ) - }) - - it("should increment the account's total votes for the group", async () => { - assertEqualBN( - await election.getTotalVotesForGroupByAccount(group, voter), - value.times(2) - ) - }) - - it("should increment the account's total votes", async () => { - assertEqualBN(await election.getTotalVotesByAccount(voter), value.times(2)) - }) - - it('should increment the total votes for the group', async () => { - assertEqualBN(await election.getTotalVotesForGroup(group), value.times(2)) - }) - - it('should increment the total votes', async () => { - assertEqualBN(await election.getTotalVotes(), value.times(2)) - }) - - it("should decrement the account's nonvoting locked gold balance", async () => { - assertEqualBN(await mockLockedGold.nonvotingAccountBalance(voter), 0) - }) - - it('should emit the ValidatorGroupVoteCast event', async () => { - assert.equal(response.logs.length, 1) - const log = response.logs[0] - assertContainSubset(log, { - event: 'ValidatorGroupVoteCast', - args: { - account: voter, - group, - value: new BigNumber(value), - }, - }) - }) - }) - }) - }) - - describe('when the voter does not have sufficient non-voting balance', () => { - beforeEach(async () => { - await mockLockedGold.incrementNonvotingAccountBalance(voter, value.minus(1)) - }) - - it('should revert', async () => { - await assertTransactionRevertWithReason( - election.vote(group, value, NULL_ADDRESS, NULL_ADDRESS), - 'SafeMath: subtraction overflow' - ) - }) - }) - }) - - describe('when the voter cannot vote for an additional group', () => { - let newGroup: string - beforeEach(async () => { - await mockLockedGold.incrementNonvotingAccountBalance(voter, value) - for (let i = 0; i < maxNumGroupsVotedFor.toNumber(); i++) { - newGroup = accounts[i + 2] - await setupGroupAndVote(newGroup, group, [accounts[9]]) - } - }) - - it('should revert', async () => { - await assertTransactionRevertWithReason( - election.vote(group, value.minus(maxNumGroupsVotedFor), newGroup, NULL_ADDRESS), - 'Voted for too many groups' - ) - }) - }) - - describe('when the voter is over maxNumGroupsVotedFor but can vote for additional groups', () => { - let newGroup: string - beforeEach(async () => { - await mockLockedGold.incrementNonvotingAccountBalance(voter, value) - for (let i = 0; i < maxNumGroupsVotedFor.toNumber(); i++) { - newGroup = accounts[i + 2] - await setupGroupAndVote(newGroup, group, [accounts[9]]) - } - newGroup = accounts[maxNumGroupsVotedFor.toNumber() + 2] - await setupGroupAndVote(newGroup, group, [accounts[9]], false) - await election.setAllowedToVoteOverMaxNumberOfGroups(true) - }) - - it('should allow to vote for another group', async () => { - const valueToVoteFor = value.minus(maxNumGroupsVotedFor) - const resp = await election.vote(group, valueToVoteFor, newGroup, NULL_ADDRESS) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ValidatorGroupVoteCast', - args: { - account: voter, - group, - value: new BigNumber(valueToVoteFor), - }, - }) - }) - - it('should total votes by account since max number of groups was not reached', async () => { - const totalVotes = await election.getTotalVotesByAccount(accounts[0]) - assertEqualBN(totalVotes, maxNumGroupsVotedFor) - }) - - describe('When over maximum number of groups voted', () => { - const originallyNotVotedWithAmount = 1 - const account0FirstGroupVote = value - .minus(maxNumGroupsVotedFor) - .minus(originallyNotVotedWithAmount) - beforeEach(async () => { - await election.vote(group, account0FirstGroupVote, newGroup, NULL_ADDRESS) - }) - - it('should revert when turning off of setAllowedToVoteOverMaxNumberOfGroups', async () => { - await assertTransactionRevertWithReason( - election.setAllowedToVoteOverMaxNumberOfGroups(false), - 'Too many groups voted for!' - ) - }) - - it('should return return only last voted with since votes were not manually counted', async () => { - const totalVotes = await election.getTotalVotesByAccount(accounts[0]) - assertEqualBN(totalVotes, account0FirstGroupVote) - }) - - describe('When total votes are manually counted on', () => { - beforeEach(async () => { - for (let i = 0; i < maxNumGroupsVotedFor.toNumber(); i++) { - newGroup = accounts[i + 2] - await election.updateTotalVotesByAccountForGroup(accounts[0], newGroup) - } - await election.updateTotalVotesByAccountForGroup(accounts[0], group) - }) - - it('should return total votes by account', async () => { - const totalVotes = await election.getTotalVotesByAccount(accounts[0]) - assertEqualBN(totalVotes, value.minus(originallyNotVotedWithAmount)) - }) - - describe('When votes revoked', () => { - const revokeDiff = 100 - const revokeValue = account0FirstGroupVote.minus(100) - - beforeEach(async () => { - await election.revokePending(group, revokeValue, accounts[4], NULL_ADDRESS, 3, { - from: accounts[0], - }) - }) - - it('should return lowered total number of votes', async () => { - const totalVotes = await election.getTotalVotesByAccount(accounts[0]) - assertEqualBN(totalVotes, maxNumGroupsVotedFor.plus(revokeDiff)) - }) - }) - }) - - describe('When votes are being activated', () => { - const rewardValue = new BigNumber(1000000) - beforeEach(async () => { - await mineBlocks(EPOCH, web3) - await election.activateForAccount(group, voter) - }) - - it("should increment the account's active votes for the group", async () => { - assertEqualBN( - await election.getActiveVotesForGroupByAccount(group, voter), - account0FirstGroupVote - ) - }) - - it('should return correct value when manually counted', async () => { - for (let i = 0; i < maxNumGroupsVotedFor.toNumber(); i++) { - newGroup = accounts[i + 2] - await election.updateTotalVotesByAccountForGroup(accounts[0], newGroup) - } - await election.updateTotalVotesByAccountForGroup(accounts[0], group) - - const totalVotes = await election.getTotalVotesByAccount(accounts[0]) - assertEqualBN(totalVotes, value.minus(originallyNotVotedWithAmount)) - }) - - describe('When awards are distributed', () => { - beforeEach(async () => { - await election.distributeEpochRewards(group, rewardValue, newGroup, NULL_ADDRESS) - }) - - it('should revoke active votes (more then original votes without rewards)', async () => { - await election.revokeActive(group, value, newGroup, NULL_ADDRESS, 3) - assertEqualBN( - await election.getActiveVotesForGroupByAccount(group, voter), - rewardValue.minus(maxNumGroupsVotedFor).minus(originallyNotVotedWithAmount) - ) - }) - - describe('When more votes than active is revoked', () => { - beforeEach(async () => { - await election.revokeActive(group, value, newGroup, NULL_ADDRESS, 3) - }) - - it('should return correct value when manually counted', async () => { - for (let i = 0; i < maxNumGroupsVotedFor.toNumber(); i++) { - newGroup = accounts[i + 2] - await election.updateTotalVotesByAccountForGroup(accounts[0], newGroup) - } - await election.updateTotalVotesByAccountForGroup(accounts[0], group) - - const totalVotes = await election.getTotalVotesByAccount(accounts[0]) - assertEqualBN(totalVotes, rewardValue.minus(originallyNotVotedWithAmount)) - }) - }) - - describe('When total votes are manually counted on rewards are being distributed', () => { - beforeEach(async () => { - for (let i = 0; i < maxNumGroupsVotedFor.toNumber(); i++) { - newGroup = accounts[i + 2] - await election.updateTotalVotesByAccountForGroup(accounts[0], newGroup) - } - await election.updateTotalVotesByAccountForGroup(accounts[0], group) - }) - - it('should return total votes by account', async () => { - const totalVotes = await election.getTotalVotesByAccount(accounts[0]) - assertEqualBN( - totalVotes, - value.plus(rewardValue).minus(originallyNotVotedWithAmount) - ) - }) - - it('should increase total votes count once voted', async () => { - await election.vote( - newGroup, - originallyNotVotedWithAmount, - accounts[3], - group, - { from: accounts[0] } - ) - - const totalVotes = await election.getTotalVotesByAccount(accounts[0]) - assertEqualBN(totalVotes, value.plus(rewardValue)) - }) - }) - }) - }) - }) - }) - }) - - describe('when the group cannot receive votes', () => { - beforeEach(async () => { - await mockLockedGold.setTotalLockedGold(value.div(2).minus(1)) - await mockValidators.setMembers(group, [accounts[9]]) - await mockValidators.setNumRegisteredValidators(1) - assertEqualBN(await election.getNumVotesReceivable(group), value.minus(2)) - }) - - it('should revert', async () => { - await assertTransactionRevertWithReason( - election.vote(group, value, NULL_ADDRESS, NULL_ADDRESS), - 'Group cannot receive votes' - ) - }) - }) - }) - - describe('when the group is not eligible', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - election.vote(group, value, NULL_ADDRESS, NULL_ADDRESS), - 'Group not eligible' - ) - }) - }) - }) - - describe('#activate', () => { - const voter = accounts[0] - const group = accounts[1] - const value = 1000 - beforeEach(async () => { - await mockValidators.setMembers(group, [accounts[9]]) - await registry.setAddressFor(CeloContractName.Validators, accounts[0]) - await election.markGroupEligible(group, NULL_ADDRESS, NULL_ADDRESS) - await registry.setAddressFor(CeloContractName.Validators, mockValidators.address) - await mockLockedGold.setTotalLockedGold(value) - await mockValidators.setMembers(group, [accounts[9]]) - await mockValidators.setNumRegisteredValidators(1) - await mockLockedGold.incrementNonvotingAccountBalance(voter, value) - }) - - describe('when the voter has pending votes', () => { - beforeEach(async () => { - await election.vote(group, value, NULL_ADDRESS, NULL_ADDRESS) - }) - - describe('when an epoch boundary has passed since the pending votes were made', () => { - let resp: any - beforeEach(async () => { - await mineBlocks(EPOCH, web3) - resp = await election.activate(group) - }) - - it("should decrement the account's pending votes for the group", async () => { - assertEqualBN(await election.getPendingVotesForGroupByAccount(group, voter), 0) - }) - - it("should increment the account's active votes for the group", async () => { - assertEqualBN(await election.getActiveVotesForGroupByAccount(group, voter), value) - }) - - it("should not modify the account's total votes for the group", async () => { - assertEqualBN(await election.getTotalVotesForGroupByAccount(group, voter), value) - }) - - it("should not modify the account's total votes", async () => { - assertEqualBN(await election.getTotalVotesByAccount(voter), value) - }) - - it('should not modify the total votes for the group', async () => { - assertEqualBN(await election.getTotalVotesForGroup(group), value) - }) - - it('should not modify the total votes', async () => { - assertEqualBN(await election.getTotalVotes(), value) - }) - - it('should emit the ValidatorGroupVoteActivated event', async () => { - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ValidatorGroupVoteActivated', - args: { - account: voter, - group, - value: new BigNumber(value), - }, - }) - }) - - describe('when another voter activates votes', () => { - const voter2 = accounts[2] - const value2 = 573 - beforeEach(async () => { - await mockLockedGold.incrementNonvotingAccountBalance(voter2, value2) - await election.vote(group, value2, NULL_ADDRESS, NULL_ADDRESS, { from: voter2 }) - await mineBlocks(EPOCH, web3) - await election.activate(group, { from: voter2 }) - }) - - it("should not modify the first account's active votes for the group", async () => { - assertEqualBN(await election.getActiveVotesForGroupByAccount(group, voter), value) - }) - - it("should not modify the first account's total votes for the group", async () => { - assertEqualBN(await election.getTotalVotesForGroupByAccount(group, voter), value) - }) - - it("should not modify the first account's total votes", async () => { - assertEqualBN(await election.getTotalVotesByAccount(voter), value) - }) - - it("should decrement the second account's pending votes for the group", async () => { - assertEqualBN(await election.getPendingVotesForGroupByAccount(group, voter2), 0) - }) - - it("should increment the second account's active votes for the group", async () => { - assertEqualBN(await election.getActiveVotesForGroupByAccount(group, voter2), value2) - }) - - it("should not modify the second account's total votes for the group", async () => { - assertEqualBN(await election.getTotalVotesForGroupByAccount(group, voter2), value2) - }) - - it("should not modify the second account's total votes", async () => { - assertEqualBN(await election.getTotalVotesByAccount(voter2), value2) - }) - - it('should not modify the total votes for the group', async () => { - assertEqualBN(await election.getTotalVotesForGroup(group), value + value2) - }) - - it('should not modify the total votes', async () => { - assertEqualBN(await election.getTotalVotes(), value + value2) - }) - }) - }) - - describe('when an epoch boundary has not passed since the pending votes were made', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - election.activate(group), - 'Pending vote epoch not passed' - ) - }) - }) - }) - - describe('when the voter does not have pending votes', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - election.activate(group), - 'Vote value cannot be zero' - ) - }) - }) - }) - - describe('#activateForAccount', () => { - const voter = accounts[0] - const group = accounts[1] - const value = 1000 - beforeEach(async () => { - await mockValidators.setMembers(group, [accounts[9]]) - await registry.setAddressFor(CeloContractName.Validators, accounts[0]) - await election.markGroupEligible(group, NULL_ADDRESS, NULL_ADDRESS) - await registry.setAddressFor(CeloContractName.Validators, mockValidators.address) - await mockLockedGold.setTotalLockedGold(value) - await mockValidators.setMembers(group, [accounts[9]]) - await mockValidators.setNumRegisteredValidators(1) - await mockLockedGold.incrementNonvotingAccountBalance(voter, value) - }) - - describe('when the voter has pending votes', () => { - beforeEach(async () => { - await election.vote(group, value, NULL_ADDRESS, NULL_ADDRESS) - }) - - describe('when an epoch boundary has passed since the pending votes were made', () => { - let resp: any - beforeEach(async () => { - await mineBlocks(EPOCH, web3) - resp = await election.activateForAccount(group, voter) - }) - - it("should decrement the account's pending votes for the group", async () => { - assertEqualBN(await election.getPendingVotesForGroupByAccount(group, voter), 0) - }) - - it("should increment the account's active votes for the group", async () => { - assertEqualBN(await election.getActiveVotesForGroupByAccount(group, voter), value) - }) - - it("should not modify the account's total votes for the group", async () => { - assertEqualBN(await election.getTotalVotesForGroupByAccount(group, voter), value) - }) - - it("should not modify the account's total votes", async () => { - assertEqualBN(await election.getTotalVotesByAccount(voter), value) - }) - - it('should not modify the total votes for the group', async () => { - assertEqualBN(await election.getTotalVotesForGroup(group), value) - }) - - it('should not modify the total votes', async () => { - assertEqualBN(await election.getTotalVotes(), value) - }) - - it('should emit the ValidatorGroupVoteActivated event', async () => { - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ValidatorGroupVoteActivated', - args: { - account: voter, - group, - value: new BigNumber(value), - }, - }) - }) - - describe('when another voter activates votes', () => { - const voter2 = accounts[2] - const value2 = 573 - beforeEach(async () => { - await mockLockedGold.incrementNonvotingAccountBalance(voter2, value2) - await election.vote(group, value2, NULL_ADDRESS, NULL_ADDRESS, { from: voter2 }) - await mineBlocks(EPOCH, web3) - await election.activateForAccount(group, voter2, { from: voter }) - }) - - it("should not modify the first account's active votes for the group", async () => { - assertEqualBN(await election.getActiveVotesForGroupByAccount(group, voter), value) - }) - - it("should not modify the first account's total votes for the group", async () => { - assertEqualBN(await election.getTotalVotesForGroupByAccount(group, voter), value) - }) - - it("should not modify the first account's total votes", async () => { - assertEqualBN(await election.getTotalVotesByAccount(voter), value) - }) - - it("should decrement the second account's pending votes for the group", async () => { - assertEqualBN(await election.getPendingVotesForGroupByAccount(group, voter2), 0) - }) - - it("should increment the second account's active votes for the group", async () => { - assertEqualBN(await election.getActiveVotesForGroupByAccount(group, voter2), value2) - }) - - it("should not modify the second account's total votes for the group", async () => { - assertEqualBN(await election.getTotalVotesForGroupByAccount(group, voter2), value2) - }) - - it("should not modify the second account's total votes", async () => { - assertEqualBN(await election.getTotalVotesByAccount(voter2), value2) - }) - - it('should not modify the total votes for the group', async () => { - assertEqualBN(await election.getTotalVotesForGroup(group), value + value2) - }) - - it('should not modify the total votes', async () => { - assertEqualBN(await election.getTotalVotes(), value + value2) - }) - }) - }) - - describe('when an epoch boundary has not passed since the pending votes were made', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - election.activateForAccount(group, voter), - 'Pending vote epoch not passed' - ) - }) - }) - }) - - describe('when the voter does not have pending votes', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - election.activateForAccount(group, voter), - 'Vote value cannot be zero' - ) - }) - }) - }) - - describe('#revokePending', () => { - const voter = accounts[0] - const group = accounts[1] - const value = 1000 - describe('when the voter has pending votes', () => { - beforeEach(async () => { - await mockValidators.setMembers(group, [accounts[9]]) - await registry.setAddressFor(CeloContractName.Validators, accounts[0]) - await election.markGroupEligible(group, NULL_ADDRESS, NULL_ADDRESS) - await registry.setAddressFor(CeloContractName.Validators, mockValidators.address) - await mockLockedGold.setTotalLockedGold(value) - await mockValidators.setNumRegisteredValidators(1) - await mockLockedGold.incrementNonvotingAccountBalance(voter, value) - await election.vote(group, value, NULL_ADDRESS, NULL_ADDRESS) - }) - - describe('when the validator group has votes but is ineligible', () => { - const index = 0 - const revokedValue = value - 1 - const remaining = value - revokedValue - let resp: any - beforeEach(async () => { - await registry.setAddressFor(CeloContractName.Validators, accounts[0]) - await election.markGroupIneligible(group) - resp = await election.revokePending( - group, - revokedValue, - NULL_ADDRESS, - NULL_ADDRESS, - index - ) - }) - - it("should decrement the account's pending votes for the group", async () => { - assertEqualBN(await election.getPendingVotesForGroupByAccount(group, voter), remaining) - }) - - it("should decrement the account's total votes for the group", async () => { - assertEqualBN(await election.getTotalVotesForGroupByAccount(group, voter), remaining) - }) - - it("should decrement the account's total votes", async () => { - assertEqualBN(await election.getTotalVotesByAccount(voter), remaining) - }) - - it('should decrement the total votes for the group', async () => { - assertEqualBN(await election.getTotalVotesForGroup(group), remaining) - }) - - it('should decrement the total votes', async () => { - assertEqualBN(await election.getTotalVotes(), remaining) - }) - - it("should increment the account's nonvoting locked gold balance", async () => { - assertEqualBN(await mockLockedGold.nonvotingAccountBalance(voter), revokedValue) - }) - - it('should emit the ValidatorGroupPendingVoteRevoked event', async () => { - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ValidatorGroupPendingVoteRevoked', - args: { - account: voter, - group, - value: new BigNumber(revokedValue), - }, - }) - }) - }) - - describe('when the revoked value is less than the pending votes', () => { - const index = 0 - const revokedValue = value - 1 - const remaining = value - revokedValue - let resp: any - beforeEach(async () => { - resp = await election.revokePending( - group, - revokedValue, - NULL_ADDRESS, - NULL_ADDRESS, - index - ) - }) - - it("should decrement the account's pending votes for the group", async () => { - assertEqualBN(await election.getPendingVotesForGroupByAccount(group, voter), remaining) - }) - - it("should decrement the account's total votes for the group", async () => { - assertEqualBN(await election.getTotalVotesForGroupByAccount(group, voter), remaining) - }) - - it("should decrement the account's total votes", async () => { - assertEqualBN(await election.getTotalVotesByAccount(voter), remaining) - }) - - it('should decrement the total votes for the group', async () => { - assertEqualBN(await election.getTotalVotesForGroup(group), remaining) - }) - - it('should decrement the total votes', async () => { - assertEqualBN(await election.getTotalVotes(), remaining) - }) - - it("should increment the account's nonvoting locked gold balance", async () => { - assertEqualBN(await mockLockedGold.nonvotingAccountBalance(voter), revokedValue) - }) - - it('should emit the ValidatorGroupPendingVoteRevoked event', async () => { - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ValidatorGroupPendingVoteRevoked', - args: { - account: voter, - group, - value: new BigNumber(revokedValue), - }, - }) - }) - }) - - describe('when the revoked value is equal to the pending votes', () => { - describe('when the correct index is provided', () => { - const index = 0 - beforeEach(async () => { - await election.revokePending(group, value, NULL_ADDRESS, NULL_ADDRESS, index) - }) - - it('should remove the group to the list of groups the account has voted for', async () => { - assert.deepEqual(await election.getGroupsVotedForByAccount(voter), []) - }) - }) - - describe('when the wrong index is provided', () => { - const index = 1 - it('should revert', async () => { - await assertTransactionRevertWithReason( - election.revokePending(group, value, NULL_ADDRESS, NULL_ADDRESS, index), - 'Bad index' - ) - }) - }) - }) - - describe('when the revoked value is greater than the pending votes', () => { - const index = 0 - it('should revert', async () => { - await assertTransactionRevertWithReason( - election.revokePending(group, value + 1, NULL_ADDRESS, NULL_ADDRESS, index), - 'Vote value larger than pending votes' - ) - }) - }) - }) - }) - - describe('#revokeActive', () => { - const voter0 = accounts[0] - const voter1 = accounts[1] - const group = accounts[2] - const voteValue0 = 1000 - const reward0 = 111 - const voteValue1 = 1000 - describe('when the voter has active votes', () => { - const assertConsistentSums = async () => { - const active0 = await election.getActiveVotesForGroupByAccount(group, voter0) - const active1 = await election.getActiveVotesForGroupByAccount(group, voter1) - const activeTotal = await election.getActiveVotesForGroup(group) - // This can vary by up to 1 wei due to rounding errors. - assertAlmostEqualBN(activeTotal, active0.plus(active1), 1) - const pending0 = await election.getPendingVotesForGroupByAccount(group, voter0) - const pending1 = await election.getPendingVotesForGroupByAccount(group, voter1) - const pendingTotal = pending0.plus(pending1) - const totalGroup = await election.getTotalVotesForGroup(group) - // This can vary by up to 1 wei due to rounding errors. - assertAlmostEqualBN(totalGroup, activeTotal.plus(pendingTotal), 1) - const total = await election.getTotalVotes() - assertEqualBN(total, totalGroup) - } - - beforeEach(async () => { - await mockValidators.setMembers(group, [accounts[9]]) - await registry.setAddressFor(CeloContractName.Validators, accounts[0]) - await election.markGroupEligible(group, NULL_ADDRESS, NULL_ADDRESS) - await registry.setAddressFor(CeloContractName.Validators, mockValidators.address) - await mockLockedGold.setTotalLockedGold(voteValue0 + voteValue1) - await mockValidators.setNumRegisteredValidators(1) - await mockLockedGold.incrementNonvotingAccountBalance(voter0, voteValue0) - await mockLockedGold.incrementNonvotingAccountBalance(voter1, voteValue1) - // Gives 1000 units to voter 0 - await election.vote(group, voteValue0, NULL_ADDRESS, NULL_ADDRESS) - await assertConsistentSums() - await mineBlocks(EPOCH, web3) - await election.activate(group) - await assertConsistentSums() - - // Makes those 1000 units represent 1111 votes. - await election.distributeEpochRewards(group, reward0, NULL_ADDRESS, NULL_ADDRESS) - await assertConsistentSums() - - // Gives 900 units to voter 1. - await election.vote(group, voteValue1, NULL_ADDRESS, NULL_ADDRESS, { from: voter1 }) - await assertConsistentSums() - await mineBlocks(EPOCH, web3) - await election.activate(group, { from: voter1 }) - await assertConsistentSums() - }) - - describe('when the validator group has votes but is ineligible', () => { - const index = 0 - const remaining = 1 - const revokedValue = voteValue0 + reward0 - remaining - let resp: any - - beforeEach(async () => { - await registry.setAddressFor(CeloContractName.Validators, accounts[0]) - await election.markGroupIneligible(group) - resp = await election.revokeActive(group, revokedValue, accounts[1], accounts[3], index) - }) - - it('should be consistent', async () => { - await assertConsistentSums() - }) - - it("should decrement the account's active votes for the group", async () => { - assertEqualBN(await election.getActiveVotesForGroupByAccount(group, voter0), remaining) - }) - - it("should decrement the account's total votes for the group", async () => { - assertEqualBN(await election.getTotalVotesForGroupByAccount(group, voter0), remaining) - }) - - it("should decrement the account's total votes", async () => { - assertEqualBN(await election.getTotalVotesByAccount(voter0), remaining) - }) - - it('should decrement the total votes for the group', async () => { - assertEqualBN( - await election.getTotalVotesForGroup(group), - voteValue0 + reward0 + voteValue1 - revokedValue - ) - }) - - it('should decrement the total votes', async () => { - assertEqualBN( - await election.getTotalVotes(), - voteValue0 + reward0 + voteValue1 - revokedValue - ) - }) - - it("should increment the account's nonvoting locked gold balance", async () => { - assertEqualBN(await mockLockedGold.nonvotingAccountBalance(voter0), revokedValue) - }) - - it('should emit the ValidatorGroupActiveVoteRevoked event', async () => { - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ValidatorGroupActiveVoteRevoked', - args: { - account: voter0, - group, - value: new BigNumber(revokedValue), - }, - }) - }) - }) - - describe('when the revoked value is less than the active votes', () => { - const index = 0 - const remaining = 1 - const revokedValue = voteValue0 + reward0 - remaining - let resp: any - beforeEach(async () => { - resp = await election.revokeActive(group, revokedValue, NULL_ADDRESS, NULL_ADDRESS, index) - }) - - it('should be consistent', async () => { - await assertConsistentSums() - }) - - it("should decrement the account's active votes for the group", async () => { - assertEqualBN(await election.getActiveVotesForGroupByAccount(group, voter0), remaining) - }) - - it("should decrement the account's total votes for the group", async () => { - assertEqualBN(await election.getTotalVotesForGroupByAccount(group, voter0), remaining) - }) - - it("should decrement the account's total votes", async () => { - assertEqualBN(await election.getTotalVotesByAccount(voter0), remaining) - }) - - it('should decrement the total votes for the group', async () => { - assertEqualBN( - await election.getTotalVotesForGroup(group), - voteValue0 + reward0 + voteValue1 - revokedValue - ) - }) - - it('should decrement the total votes', async () => { - assertEqualBN( - await election.getTotalVotes(), - voteValue0 + reward0 + voteValue1 - revokedValue - ) - }) - - it("should increment the account's nonvoting locked gold balance", async () => { - assertEqualBN(await mockLockedGold.nonvotingAccountBalance(voter0), revokedValue) - }) - - it('should emit the ValidatorGroupActiveVoteRevoked event', async () => { - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertContainSubset(log, { - event: 'ValidatorGroupActiveVoteRevoked', - args: { - account: voter0, - group, - value: new BigNumber(revokedValue), - }, - }) - }) - }) - - describe('when the revoked value is equal to the active votes', () => { - describe('#revokeAllActive', () => { - const index = 0 - beforeEach(async () => { - await election.revokeAllActive(group, NULL_ADDRESS, NULL_ADDRESS, index) - }) - - it('should be consistent', async () => { - await assertConsistentSums() - }) - - it("should decrement all of the account's active votes for the group", async () => { - assertEqualBN(await election.getActiveVotesForGroupByAccount(group, voter0), 0) - }) - }) - - describe('when the correct index is provided', () => { - const index = 0 - const revokedValue = voteValue0 + reward0 - beforeEach(async () => { - await election.revokeActive(group, revokedValue, NULL_ADDRESS, NULL_ADDRESS, index) - }) - - it('should be consistent', async () => { - await assertConsistentSums() - }) - - it("should decrement the account's active votes for the group", async () => { - assertEqualBN(await election.getActiveVotesForGroupByAccount(group, voter0), 0) - }) - - it("should decrement the account's total votes for the group", async () => { - assertEqualBN(await election.getTotalVotesForGroupByAccount(group, voter0), 0) - }) - - it("should decrement the account's total votes", async () => { - assertEqualBN(await election.getTotalVotesByAccount(voter0), 0) - }) - - it('should decrement the total votes for the group', async () => { - assertEqualBN(await election.getTotalVotesForGroup(group), voteValue1) - }) - - it('should decrement the total votes', async () => { - assertEqualBN(await election.getTotalVotes(), voteValue1) - }) - - it("should increment the account's nonvoting locked gold balance", async () => { - assertEqualBN(await mockLockedGold.nonvotingAccountBalance(voter0), revokedValue) - }) - - it('should remove the group to the list of groups the account has voted for', async () => { - assert.deepEqual(await election.getGroupsVotedForByAccount(voter0), []) - }) - }) - - describe('when the wrong index is provided', () => { - const index = 1 - it('should revert', async () => { - await assertTransactionRevertWithReason( - election.revokeActive(group, voteValue0 + reward0, NULL_ADDRESS, NULL_ADDRESS, index), - 'Bad index' - ) - }) - }) - }) - - describe('when the revoked value is greater than the active votes', () => { - const index = 0 - it('should revert', async () => { - await assertTransactionRevertWithReason( - election.revokeActive( - group, - voteValue0 + reward0 + 1, - NULL_ADDRESS, - NULL_ADDRESS, - index - ), - 'Vote value larger than active votes' - ) - }) - }) - }) - }) - - describe('#electValidatorSigners', () => { - let random: MockRandomInstance - let totalLockedGold: number - const group1 = accounts[0] - const group2 = accounts[1] - const group3 = accounts[2] - const validator1 = accounts[3] - const validator2 = accounts[4] - const validator3 = accounts[5] - const validator4 = accounts[6] - const validator5 = accounts[7] - const validator6 = accounts[8] - const validator7 = accounts[9] - - const hash1 = '0xa5b9d60f32436310afebcfda832817a68921beb782fabf7915cc0460b443116a' - - // If voterN votes for groupN: - // group1 gets 20 votes per member - // group2 gets 25 votes per member - // group3 gets 30 votes per member - // We cannot make any guarantee with respect to their ordering. - const voter1 = { address: accounts[0], weight: 80 } - const voter2 = { address: accounts[1], weight: 50 } - const voter3 = { address: accounts[2], weight: 30 } - totalLockedGold = voter1.weight + voter2.weight + voter3.weight - const assertSameAddresses = (actual: string[], expected: string[]) => { - assert.sameMembers( - actual.map((x) => x.toLowerCase()), - expected.map((x) => x.toLowerCase()) - ) - } - - const setRandomness = async (hash: string) => - random.addTestRandomness((await web3.eth.getBlockNumber()) + 1, hash) - - beforeEach(async () => { - random = await MockRandom.new() - await registry.setAddressFor(CeloContractName.Random, random.address) - }) - - describe('when there is a large number of groups', () => { - const numbers: any = {} - beforeEach(async () => { - await mockLockedGold.setTotalLockedGold(new BigNumber(1e25)) - await mockValidators.setNumRegisteredValidators(400) - await mockLockedGold.incrementNonvotingAccountBalance(voter1.address, new BigNumber(1e25)) - await election.setElectabilityThreshold(0) - await election.setElectableValidators(10, 100) - - await election.setMaxNumGroupsVotedFor(200) - let prev = NULL_ADDRESS - let randomVotes = [] - for (let i = 0; i < 100; i++) { - randomVotes.push(Math.floor(Math.random() * 1e14)) - } - const pad = (a: string) => { - let res = a - while (res.length < 42) { - res = res + 'f' - } - return res - } - randomVotes = randomVotes.sort((a, b) => b - a) - for (let i = 0; i < 100; i++) { - await mockValidators.setMembers(pad('0x00' + i), [ - pad('0x1a' + i), - pad('0x2a' + i), - pad('0x3a' + i), - pad('0x4a' + i), - ]) - numbers[pad('0x1a' + i)] = randomVotes[i] - numbers[pad('0x2a' + i)] = randomVotes[i] / 2 - numbers[pad('0x3a' + i)] = randomVotes[i] / 3 - numbers[pad('0x4a' + i)] = randomVotes[i] / 4 - await registry.setAddressFor(CeloContractName.Validators, accounts[0]) - await election.markGroupEligible(pad('0x00' + i), NULL_ADDRESS, prev) - await registry.setAddressFor(CeloContractName.Validators, mockValidators.address) - await election.vote(pad('0x00' + i), randomVotes[i], NULL_ADDRESS, prev, { - from: voter1.address, - }) - prev = pad('0x00' + i) - } - }) - it('can elect correct validators', async () => { - const lst = await election.electValidatorSigners() - const smallest = lst - .map(normalizeAddressWith0x) - .map((a) => numbers[a]) - .sort((a, b) => a - b)[0] - // TODO fix types - const number100th = (Object as any).values(numbers).sort((a: any, b: any) => b - a)[99] - assert.equal(smallest, number100th) - }) - }) - - describe('when there are some groups', () => { - beforeEach(async () => { - await mockValidators.setMembers(group1, [validator1, validator2, validator3, validator4]) - await mockValidators.setMembers(group2, [validator5, validator6]) - await mockValidators.setMembers(group3, [validator7]) - - await registry.setAddressFor(CeloContractName.Validators, accounts[0]) - await election.markGroupEligible(group1, NULL_ADDRESS, NULL_ADDRESS) - await election.markGroupEligible(group2, NULL_ADDRESS, group1) - await election.markGroupEligible(group3, NULL_ADDRESS, group2) - await registry.setAddressFor(CeloContractName.Validators, mockValidators.address) - - for (const voter of [voter1, voter2, voter3]) { - await mockLockedGold.incrementNonvotingAccountBalance(voter.address, voter.weight) - } - await mockLockedGold.setTotalLockedGold(totalLockedGold) - await mockValidators.setNumRegisteredValidators(7) - }) - - describe('when a single group has >= minElectableValidators as members and received votes', () => { - beforeEach(async () => { - await election.vote(group1, voter1.weight, group2, NULL_ADDRESS, { from: voter1.address }) - }) - - it("should return that group's member list", async () => { - await setRandomness(hash1) - assertSameAddresses(await election.electValidatorSigners(), [ - validator1, - validator2, - validator3, - validator4, - ]) - }) - }) - - describe("when > maxElectableValidators members' groups receive votes", () => { - beforeEach(async () => { - await election.vote(group1, voter1.weight, group2, NULL_ADDRESS, { from: voter1.address }) - await election.vote(group2, voter2.weight, NULL_ADDRESS, group1, { from: voter2.address }) - await election.vote(group3, voter3.weight, NULL_ADDRESS, group2, { from: voter3.address }) - }) - - it('should return maxElectableValidators elected validators', async () => { - await setRandomness(hash1) - assertSameAddresses(await election.electValidatorSigners(), [ - validator1, - validator2, - validator3, - validator5, - validator6, - validator7, - ]) - }) - }) - - describe('when a group receives enough votes for > n seats but only has n members', () => { - beforeEach(async () => { - // By incrementing the total votes by 80, we allow group3 to receive 80 votes from voter3. - const increment = 80 - const votes = 80 - await mockLockedGold.incrementNonvotingAccountBalance(voter3.address, increment) - await mockLockedGold.setTotalLockedGold(totalLockedGold + increment) - await election.vote(group3, votes, group2, NULL_ADDRESS, { from: voter3.address }) - await election.vote(group1, voter1.weight, NULL_ADDRESS, group3, { from: voter1.address }) - await election.vote(group2, voter2.weight, NULL_ADDRESS, group1, { from: voter2.address }) - }) - - it('should elect only n members from that group', async () => { - await setRandomness(hash1) - assertSameAddresses(await election.electValidatorSigners(), [ - validator7, - validator1, - validator2, - validator3, - validator5, - validator6, - ]) - }) - }) - - describe('when a group does not receive `electabilityThresholdVotes', () => { - beforeEach(async () => { - const thresholdExcludingGroup3 = (voter3.weight + 1) / totalLockedGold - await election.setElectabilityThreshold(toFixed(thresholdExcludingGroup3)) - await election.vote(group1, voter1.weight, group2, NULL_ADDRESS, { from: voter1.address }) - await election.vote(group2, voter2.weight, NULL_ADDRESS, group1, { from: voter2.address }) - await election.vote(group3, voter3.weight, NULL_ADDRESS, group2, { from: voter3.address }) - }) - - it('should not elect any members from that group', async () => { - await setRandomness(hash1) - assertSameAddresses(await election.electValidatorSigners(), [ - validator1, - validator2, - validator3, - validator4, - validator5, - validator6, - ]) - }) - }) - - describe('when there are not enough electable validators', () => { - beforeEach(async () => { - await election.vote(group2, voter2.weight, group1, NULL_ADDRESS, { from: voter2.address }) - await election.vote(group3, voter3.weight, NULL_ADDRESS, group2, { from: voter3.address }) - }) - - it('should revert', async () => { - await setRandomness(hash1) - await assertRevert(election.electValidatorSigners()) - }) - }) - }) - }) - - describe('#getGroupEpochRewards', () => { - const voter = accounts[0] - const group1 = accounts[1] - const group2 = accounts[2] - const voteValue1 = new BigNumber(2000000000) - const voteValue2 = new BigNumber(1000000000) - const totalRewardValue = new BigNumber(3000000000) - beforeEach(async () => { - await registry.setAddressFor(CeloContractName.Validators, accounts[0]) - await election.markGroupEligible(group1, NULL_ADDRESS, NULL_ADDRESS) - await election.markGroupEligible(group2, NULL_ADDRESS, group1) - await registry.setAddressFor(CeloContractName.Validators, mockValidators.address) - await mockLockedGold.setTotalLockedGold(voteValue1.plus(voteValue2)) - await mockValidators.setMembers(group1, [accounts[8]]) - await mockValidators.setMembers(group2, [accounts[9]]) - await mockValidators.setNumRegisteredValidators(2) - await mockLockedGold.incrementNonvotingAccountBalance(voter, voteValue1.plus(voteValue2)) - await election.vote(group1, voteValue1, group2, NULL_ADDRESS) - await election.vote(group2, voteValue2, NULL_ADDRESS, group1) - }) - - describe('when one group has active votes', () => { - beforeEach(async () => { - await mineBlocks(EPOCH, web3) - await election.activate(group1) - }) - - describe('when the group meets the locked gold requirements ', () => { - describe('when group uptime is 100%', () => { - it('should return the total reward value', async () => { - assertEqualBN( - await election.getGroupEpochRewards(group1, totalRewardValue, [fixed1]), - totalRewardValue - ) - }) - }) - - describe('when group uptime is less than 100%', () => { - it('should return part of the total reward value', async () => { - assertEqualBN( - await election.getGroupEpochRewards(group1, totalRewardValue, [toFixed(0.5)]), - totalRewardValue.idiv(2) - ) - }) - }) - - describe('when group uptime is zero', () => { - it('should return zero', async () => { - assertEqualBN(await election.getGroupEpochRewards(group1, totalRewardValue, [0]), 0) - }) - }) - }) - - describe('when the group does not meet the locked gold requirements ', () => { - beforeEach(async () => { - await mockValidators.setDoesNotMeetAccountLockedGoldRequirements(group1) - }) - - it('should return zero', async () => { - assertEqualBN(await election.getGroupEpochRewards(group1, totalRewardValue, [fixed1]), 0) - }) - }) - }) - - describe('when two groups have active votes', () => { - const expectedGroup1EpochRewards = voteValue1 - .div(voteValue1.plus(voteValue2)) - .times(totalRewardValue) - .dp(0) - .minus(1) // minus 1 wei for rounding errors. - beforeEach(async () => { - await mineBlocks(EPOCH, web3) - await election.activate(group1) - await election.activate(group2) - }) - - describe('when one group does not meet the locked gold requirements ', () => { - beforeEach(async () => { - await mockValidators.setDoesNotMeetAccountLockedGoldRequirements(group2) - }) - - it('should return zero for that group', async () => { - assertEqualBN(await election.getGroupEpochRewards(group2, totalRewardValue, [fixed1]), 0) - }) - - it('should return the proportional reward value for the other group', async () => { - assertEqualBN( - await election.getGroupEpochRewards(group1, totalRewardValue, [fixed1]), - expectedGroup1EpochRewards - ) - }) - }) - }) - - describe('when the group does not have active votes', () => { - describe('when the group meets the locked gold requirements ', () => { - it('should return zero', async () => { - assertEqualBN(await election.getGroupEpochRewards(group1, totalRewardValue, [fixed1]), 0) - }) - }) - }) - }) - - describe('#distributeEpochRewards', () => { - const voter = accounts[0] - const group = accounts[1] - const voteValue = new BigNumber(1000000) - const rewardValue = new BigNumber(1000000) - beforeEach(async () => { - await registry.setAddressFor(CeloContractName.Validators, accounts[0]) - await election.markGroupEligible(group, NULL_ADDRESS, NULL_ADDRESS) - await registry.setAddressFor(CeloContractName.Validators, mockValidators.address) - await mockLockedGold.setTotalLockedGold(voteValue) - await mockValidators.setMembers(group, [accounts[9]]) - await mockValidators.setNumRegisteredValidators(1) - await mockLockedGold.incrementNonvotingAccountBalance(voter, voteValue) - await election.vote(group, voteValue, NULL_ADDRESS, NULL_ADDRESS) - await mineBlocks(EPOCH, web3) - await election.activate(group) - }) - - describe('when there is a single group with active votes', () => { - describe('when the group is eligible', () => { - beforeEach(async () => { - await election.distributeEpochRewards(group, rewardValue, NULL_ADDRESS, NULL_ADDRESS) - }) - - it("should increment the account's active votes for the group", async () => { - assertEqualBN( - await election.getActiveVotesForGroupByAccount(group, voter), - voteValue.plus(rewardValue) - ) - }) - - it("should increment the account's total votes for the group", async () => { - assertEqualBN( - await election.getTotalVotesForGroupByAccount(group, voter), - voteValue.plus(rewardValue) - ) - }) - - it("should increment account's total votes", async () => { - assertEqualBN(await election.getTotalVotesByAccount(voter), voteValue.plus(rewardValue)) - }) - - it('should increment the total votes for the group', async () => { - assertEqualBN(await election.getTotalVotesForGroup(group), voteValue.plus(rewardValue)) - }) - - it('should increment the total votes', async () => { - assertEqualBN(await election.getTotalVotes(), voteValue.plus(rewardValue)) - }) - }) - }) - - describe('when there are two groups with active votes', () => { - const voter2 = accounts[2] - const group2 = accounts[3] - const voteValue2 = new BigNumber(1000000) - const rewardValue2 = new BigNumber(10000000) - beforeEach(async () => { - await registry.setAddressFor(CeloContractName.Validators, accounts[0]) - await election.markGroupEligible(group2, NULL_ADDRESS, group) - await registry.setAddressFor(CeloContractName.Validators, mockValidators.address) - await mockLockedGold.setTotalLockedGold(voteValue.plus(voteValue2)) - await mockValidators.setNumRegisteredValidators(2) - await mockLockedGold.incrementNonvotingAccountBalance(voter2, voteValue2) - // Split voter2's vote between the two groups. - await election.vote(group, voteValue2.div(2), group2, NULL_ADDRESS, { from: voter2 }) - await election.vote(group2, voteValue2.div(2), NULL_ADDRESS, group, { from: voter2 }) - await mineBlocks(EPOCH, web3) - await election.activate(group, { from: voter2 }) - await election.activate(group2, { from: voter2 }) - }) - - describe('when boths groups are eligible', () => { - const expectedGroupTotalActiveVotes = voteValue.plus(voteValue2.div(2)).plus(rewardValue) - const expectedVoterActiveVotesForGroup = expectedGroupTotalActiveVotes - .times(2) - .div(3) - .dp(0, BigNumber.ROUND_FLOOR) - const expectedVoter2ActiveVotesForGroup = expectedGroupTotalActiveVotes - .div(3) - .dp(0, BigNumber.ROUND_FLOOR) - const expectedVoter2ActiveVotesForGroup2 = voteValue2.div(2).plus(rewardValue2) - beforeEach(async () => { - await election.distributeEpochRewards(group, rewardValue, group2, NULL_ADDRESS) - await election.distributeEpochRewards(group2, rewardValue2, group, NULL_ADDRESS) - }) - - it("should increment the accounts' active votes for both groups", async () => { - assertEqualBN( - await election.getActiveVotesForGroupByAccount(group, voter), - expectedVoterActiveVotesForGroup - ) - assertEqualBN( - await election.getActiveVotesForGroupByAccount(group, voter2), - expectedVoter2ActiveVotesForGroup - ) - assertEqualBN( - await election.getActiveVotesForGroupByAccount(group2, voter2), - expectedVoter2ActiveVotesForGroup2 - ) - }) - - it("should increment the accounts' total votes for both groups", async () => { - assertEqualBN( - await election.getTotalVotesForGroupByAccount(group, voter), - expectedVoterActiveVotesForGroup - ) - assertEqualBN( - await election.getTotalVotesForGroupByAccount(group, voter2), - expectedVoter2ActiveVotesForGroup - ) - assertEqualBN( - await election.getTotalVotesForGroupByAccount(group2, voter2), - expectedVoter2ActiveVotesForGroup2 - ) - }) - - it("should increment the accounts' total votes", async () => { - assertEqualBN( - await election.getTotalVotesByAccount(voter), - expectedVoterActiveVotesForGroup - ) - assertEqualBN( - await election.getTotalVotesByAccount(voter2), - expectedVoter2ActiveVotesForGroup.plus(expectedVoter2ActiveVotesForGroup2) - ) - }) - - it('should increment the total votes for the groups', async () => { - assertEqualBN(await election.getTotalVotesForGroup(group), expectedGroupTotalActiveVotes) - assertEqualBN( - await election.getTotalVotesForGroup(group2), - expectedVoter2ActiveVotesForGroup2 - ) - }) - - it('should increment the total votes', async () => { - assertEqualBN( - await election.getTotalVotes(), - expectedGroupTotalActiveVotes.plus(expectedVoter2ActiveVotesForGroup2) - ) - }) - - it('should update the ordering of the eligible groups', async () => { - assert.deepEqual(await election.getEligibleValidatorGroups(), [group2, group]) - }) - }) - }) - }) - - describe('#forceDecrementVotes', () => { - const voter = accounts[0] - const group = accounts[1] - const value = 1000 - - describe('when the account has voted for one group', () => { - beforeEach(async () => { - await mockValidators.setMembers(group, [accounts[9]]) - await registry.setAddressFor(CeloContractName.Validators, accounts[0]) - await election.markGroupEligible(group, NULL_ADDRESS, NULL_ADDRESS) - await registry.setAddressFor(CeloContractName.Validators, mockValidators.address) - await mockLockedGold.setTotalLockedGold(value) - await mockValidators.setNumRegisteredValidators(1) - await mockLockedGold.incrementNonvotingAccountBalance(voter, value) - await election.vote(group, value, NULL_ADDRESS, NULL_ADDRESS) - await registry.setAddressFor(CeloContractName.LockedGold, accounts[2]) - }) - - describe('when the account only has pending votes', () => { - describe('when the account is slashed for the total pending voted gold', () => { - const index = 0 - const slashedValue = value - const remaining = value - slashedValue - beforeEach(async () => { - await election.forceDecrementVotes( - voter, - slashedValue, - [NULL_ADDRESS], - [NULL_ADDRESS], - [index], - { - from: accounts[2], - } - ) - }) - - it('should decrement pending votes to zero', async () => { - assertEqualBN(await election.getPendingVotesForGroupByAccount(group, voter), remaining) - }) - - it('should decrement total votes to zero', async () => { - assertEqualBN(await election.getTotalVotesForGroupByAccount(group, voter), remaining) - assertEqualBN(await election.getTotalVotesByAccount(voter), remaining) - assertEqualBN(await election.getTotalVotesForGroup(group), remaining) - assertEqualBN(await election.getTotalVotes(), remaining) - }) - - it("should remove the group from the voter's voted set", async () => { - assert.deepEqual(await election.getGroupsVotedForByAccount(voter), []) - }) - }) - }) - - describe('when the account only has active votes', () => { - beforeEach(async () => { - await mineBlocks(EPOCH, web3) - await election.activate(group) - }) - - describe('when the account is slashed for the total active voting gold', () => { - const index = 0 - const slashedValue = value - const remaining = value - slashedValue - beforeEach(async () => { - await election.forceDecrementVotes( - voter, - slashedValue, - [NULL_ADDRESS], - [NULL_ADDRESS], - [index], - { - from: accounts[2], - } - ) - }) - - it('should decrement active voted gold to zero', async () => { - assertEqualBN(await election.getActiveVotesForGroupByAccount(group, voter), remaining) - }) - - it('should decrement total voted gold to zero', async () => { - assertEqualBN(await election.getTotalVotesForGroupByAccount(group, voter), remaining) - assertEqualBN(await election.getTotalVotesByAccount(voter), remaining) - assertEqualBN(await election.getTotalVotesForGroup(group), remaining) - assertEqualBN(await election.getTotalVotes(), remaining) - }) - - it("should remove the group from the voter's voted set", async () => { - assert.deepEqual(await election.getGroupsVotedForByAccount(voter), []) - }) - }) - }) - }) - - describe('when the account has voted for more than one group equally', () => { - const group2 = accounts[7] - - beforeEach(async () => { - await mockValidators.setMembers(group, [accounts[9]]) - await mockValidators.setMembers(group2, [accounts[8]]) - await registry.setAddressFor(CeloContractName.Validators, accounts[0]) - await election.markGroupEligible(group, NULL_ADDRESS, NULL_ADDRESS) - await election.markGroupEligible(group2, NULL_ADDRESS, group) - await registry.setAddressFor(CeloContractName.Validators, mockValidators.address) - await mockLockedGold.setTotalLockedGold(value) - await mockValidators.setNumRegisteredValidators(2) - await mockLockedGold.incrementNonvotingAccountBalance(voter, value) - await election.vote(group, value / 2, group2, NULL_ADDRESS) - await election.vote(group2, value / 2, NULL_ADDRESS, group) - await registry.setAddressFor(CeloContractName.LockedGold, accounts[2]) - }) - - describe('when the accounts only have pending votes', () => { - describe('when both accounts are slashed for the total pending voted gold', () => { - const slashedValue = value - const remaining = value - slashedValue - - beforeEach(async () => { - await election.forceDecrementVotes( - voter, - slashedValue, - [group2, NULL_ADDRESS], - [NULL_ADDRESS, group], - [0, 1], - { from: accounts[2] } - ) - }) - - it("should decrement both group's pending votes to zero", async () => { - assertEqualBN(await election.getPendingVotesForGroupByAccount(group, voter), remaining) - assertEqualBN(await election.getPendingVotesForGroupByAccount(group2, voter), remaining) - }) - - it("should decrement both group's total votes to zero", async () => { - assertEqualBN(await election.getTotalVotesForGroupByAccount(group, voter), remaining) - assertEqualBN(await election.getTotalVotesByAccount(voter), remaining) - assertEqualBN(await election.getTotalVotesForGroup(group), remaining) - assertEqualBN(await election.getTotalVotesForGroup(group2), remaining) - assertEqualBN(await election.getTotalVotes(), remaining) - }) - - it("should remove the groups from the voter's voted set", async () => { - assert.deepEqual(await election.getGroupsVotedForByAccount(voter), []) - }) - }) - }) - }) - - describe('when the account has voted for more than one group inequally', () => { - const group2 = accounts[7] - const value2 = value * 1.5 - - beforeEach(async () => { - await mockValidators.setMembers(group, [accounts[9]]) - await mockValidators.setMembers(group2, [accounts[8]]) - await registry.setAddressFor(CeloContractName.Validators, accounts[0]) - await election.markGroupEligible(group, NULL_ADDRESS, NULL_ADDRESS) - await election.markGroupEligible(group2, group, NULL_ADDRESS) - await registry.setAddressFor(CeloContractName.Validators, mockValidators.address) - await mockLockedGold.setTotalLockedGold(value + value2) - await mockValidators.setNumRegisteredValidators(2) - await mockLockedGold.incrementNonvotingAccountBalance(voter, value + value2) - await election.vote(group2, value2 / 2, group, NULL_ADDRESS) - await election.vote(group, value / 2, NULL_ADDRESS, group2) - }) - - describe('when both groups have both pending and active votes', async () => { - beforeEach(async () => { - await mineBlocks(EPOCH, web3) - await election.activate(group) - await mineBlocks(EPOCH, web3) - await election.activate(group2) - await election.vote(group2, value2 / 2, group, NULL_ADDRESS) - await election.vote(group, value / 2, NULL_ADDRESS, group2) - await registry.setAddressFor(CeloContractName.LockedGold, accounts[2]) - }) - - describe("when we slash 1 more vote than group 1's pending vote total", async () => { - const slashedValue = value / 2 + 1 - const remaining = value - slashedValue - beforeEach(async () => { - await election.forceDecrementVotes( - voter, - slashedValue, - [NULL_ADDRESS, NULL_ADDRESS], - [group, group2], - [0, 1], - { from: accounts[2] } - ) - }) - - it('should not affect group 2', async () => { - assertEqualBN(await election.getTotalVotesForGroupByAccount(group2, voter), value2) - assertEqualBN(await election.getTotalVotesForGroup(group2), value2) - }) - - it("should reduce group 1's votes", async () => { - assertEqualBN(await election.getTotalVotesForGroupByAccount(group, voter), remaining) - assertEqualBN(await election.getTotalVotesForGroup(group), remaining) - }) - - it("should reduce `voter`'s total votes", async () => { - assertEqualBN(await election.getTotalVotesByAccount(voter), value2 + remaining) - }) - - it("should reduce `group1`'s pending votes to 0", async () => { - assertEqualBN(await election.getPendingVotesForGroupByAccount(group, voter), 0) - }) - - it("should reduce `group1`'s' active votes by 1", async () => { - assertEqualBN(await election.getActiveVotesForGroupByAccount(group, voter), remaining) - }) - }) - - describe("when we slash all of group 1's votes and some of group 2's", async () => { - const slashedValue = value + 1 - const totalRemaining = value + value2 - slashedValue - const group1Remaining = 0 - const group2TotalRemaining = value2 - 1 - // 1 vote is removed from group2, pending is removed first - const group2PendingRemaining = value2 / 2 - 1 - const group2ActiveRemaining = value2 / 2 - beforeEach(async () => { - await election.forceDecrementVotes( - voter, - slashedValue, - [group, NULL_ADDRESS], - [NULL_ADDRESS, group2], - [0, 1], - { from: accounts[2] } - ) - }) - - it("should decrement group 1's votes to 0", async () => { - assertEqualBN( - await election.getTotalVotesForGroupByAccount(group, voter), - group1Remaining - ) - assertEqualBN(await election.getTotalVotesForGroup(group), group1Remaining) - assertEqualBN( - await election.getPendingVotesForGroupByAccount(group, voter), - group1Remaining - ) - assertEqualBN( - await election.getActiveVotesForGroupByAccount(group, voter), - group1Remaining - ) - }) - - it("should decrement group 2's total votes by 1", async () => { - assertEqualBN( - await election.getTotalVotesForGroupByAccount(group2, voter), - group2TotalRemaining - ) - assertEqualBN(await election.getTotalVotesForGroup(group2), group2TotalRemaining) - }) - - it("should reduce `voter`'s total votes", async () => { - assertEqualBN(await election.getTotalVotesByAccount(voter), totalRemaining) - }) - - it("should reduce `group2`'s pending votes by 1", async () => { - assertEqualBN( - await election.getPendingVotesForGroupByAccount(group2, voter), - group2PendingRemaining - ) - }) - - it("should not reduce `group2`'s active votes", async () => { - assertEqualBN( - await election.getActiveVotesForGroupByAccount(group2, voter), - group2ActiveRemaining - ) - }) - }) - }) - - describe('when a slash affects the election order', () => { - const slashedValue = value / 4 - const group1RemainingActiveVotes = value - slashedValue - let initialGroupOrdering = [] - - beforeEach(async () => { - await election.vote(group, value / 2, group2, NULL_ADDRESS) - await mineBlocks(EPOCH, web3) - await election.activate(group) - await mineBlocks(EPOCH, web3) - await election.activate(group2) - initialGroupOrdering = (await election.getTotalVotesForEligibleValidatorGroups())[0] - await registry.setAddressFor(CeloContractName.LockedGold, accounts[2]) - await election.forceDecrementVotes( - voter, - slashedValue, - [group, NULL_ADDRESS], - [NULL_ADDRESS, group2], - [0, 1], - { from: accounts[2] } - ) - }) - - it("should decrement group 1's total votes by 1/4", async () => { - assertEqualBN( - await election.getTotalVotesForGroupByAccount(group, voter), - group1RemainingActiveVotes - ) - assertEqualBN(await election.getTotalVotesForGroup(group), group1RemainingActiveVotes) - }) - - it('should change the ordering of the election', async () => { - const newGroupOrdering = (await election.getTotalVotesForEligibleValidatorGroups())[0] - assert.notEqual(initialGroupOrdering, newGroupOrdering) - assert.equal(initialGroupOrdering[0], newGroupOrdering[1]) - assert.equal(initialGroupOrdering[1], newGroupOrdering[0]) - }) - }) - - describe('when `forceDecrementVotes` is called with malformed inputs', () => { - describe('when called to slash more value than groups have', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - election.forceDecrementVotes( - voter, - value + value2 + 1, - [group, NULL_ADDRESS], - [NULL_ADDRESS, group2], - [0, 1], - { from: accounts[2] } - ), - 'only registered contract' - ) - }) - }) - - describe('when called to slash with incorrect lessers/greaters', () => { - it('should revert', async () => { - const slashedValue = value - // `group` should be listed as a lesser for index 0 (group2's lesser) - await assertTransactionRevertWithReason( - election.forceDecrementVotes( - voter, - slashedValue, - [NULL_ADDRESS, NULL_ADDRESS], - [NULL_ADDRESS, group2], - [0, 1], - { from: accounts[2] } - ), - 'only registered contract' - ) - }) - }) - - describe('when called to slash with incorrect indices', () => { - it('should revert', async () => { - const slashedValue = value - await assertTransactionRevertWithReason( - election.forceDecrementVotes( - voter, - slashedValue, - [group, NULL_ADDRESS], - [NULL_ADDRESS, group2], - [0, 0], - { from: accounts[2] } - ), - 'only registered contract' - ) - }) - }) - - describe('when called from an address other than the locked gold contract', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - election.forceDecrementVotes( - voter, - value, - [group, NULL_ADDRESS], - [NULL_ADDRESS, group2], - [0, 0] - ), - 'only registered contract' - ) - }) - }) - }) - }) - }) - - describe('#consistencyChecks', () => { - const debug = false - const group = accounts[0] - const voters = accounts.slice(1) - interface Account { - address: string - nonvoting: BigNumber - pending: BigNumber - active: BigNumber - } - - const debugLog = (s: string) => { - if (debug) { - // tslint:disable-next-line: no-console - console.log(s) - } - } - - const printAccount = async (account: Account) => { - if (debug) { - debugLog( - `Expected ${ - account.address - }:\n\tnonvoting: ${account.nonvoting.toFixed()}\n\tpending: ${account.pending.toFixed()}\n\tactive: ${account.active.toFixed()}` - ) - debugLog( - `Actual ${account.address}:\n\tnonvoting: ${( - await mockLockedGold.nonvotingAccountBalance(account.address) - ).toFixed()}\n\tpending: ${( - await election.getPendingVotesForGroupByAccount(group, account.address) - ).toFixed()}\n\tactive: ${( - await election.getActiveVotesForGroupByAccount(group, account.address) - ).toFixed()}\n\tunits: ${( - await election.getActiveVoteUnitsForGroupByAccount(group, account.address) - ).toFixed()}\n\ttotalunits: ${( - await election.getActiveVoteUnitsForGroup(group) - ).toFixed()}\n\ttotalVotes: ${(await election.getActiveVotesForGroup(group)).toFixed()}` - ) - } - } - - enum VoteActionType { - Vote = 1, - Activate, - RevokePending, - RevokeActive, - } - - const randomElement = (list: A[]): A => { - return list[Math.floor(BigNumber.random().times(list.length).toNumber())] - } - - const randomInteger = (max: BigNumber, min: BigNumber = new BigNumber(1)): BigNumber => { - return BigNumber.random().times(max.minus(min)).plus(min).dp(0) - } - - const makeRandomAction = async (account: Account) => { - await printAccount(account) - const actions = [] - if (account.nonvoting.gt(0)) { - actions.push(VoteActionType.Vote) - } - if (await election.hasActivatablePendingVotes(account.address, group)) { - actions.push(VoteActionType.Activate) - } - if (account.pending.gt(0)) { - actions.push(VoteActionType.RevokePending) - } - if (account.active.gt(0)) { - actions.push(VoteActionType.RevokeActive) - } - const action = randomElement(actions) - let value: string - switch (action) { - case VoteActionType.Vote: - value = randomInteger(account.nonvoting).toFixed() - debugLog(`${account.address} voting with value ${value}`) - await election.vote(group, value, NULL_ADDRESS, NULL_ADDRESS, { from: account.address }) - account.nonvoting = account.nonvoting.minus(value) - account.pending = account.pending.plus(value) - break - case VoteActionType.Activate: - value = account.pending.toFixed() - debugLog(`${account.address} activating with value ${value}`) - await election.activate(group, { from: account.address }) - account.active = account.active.plus(value) - account.pending = account.pending.minus(value) - break - case VoteActionType.RevokePending: - value = randomInteger(account.pending).toFixed() - debugLog(`${account.address} revoking pending with value ${value}`) - await election.revokePending(group, value, NULL_ADDRESS, NULL_ADDRESS, 0, { - from: account.address, - }) - account.pending = account.pending.minus(value) - account.nonvoting = account.nonvoting.plus(value) - break - case VoteActionType.RevokeActive: - value = randomInteger(account.active).toFixed() - debugLog(`${account.address} revoking active with value ${value}`) - await election.revokeActive(group, value, NULL_ADDRESS, NULL_ADDRESS, 0, { - from: account.address, - }) - account.active = account.active.minus(value) - account.nonvoting = account.nonvoting.plus(value) - break - } - return account - } - - const checkVoterInvariants = async (account: Account, delta: number = 0) => { - await printAccount(account) - debugLog(`Checking pending vote invariant for ${account.address}`) - assertEqualBN( - await election.getPendingVotesForGroupByAccount(group, account.address), - account.pending - ) - debugLog(`Checking active vote invariant for ${account.address}`) - assertAlmostEqualBN( - await election.getActiveVotesForGroupByAccount(group, account.address), - account.active, - delta - ) - debugLog(`Checking total vote invariant for ${account.address}`) - assertAlmostEqualBN( - await election.getTotalVotesForGroupByAccount(group, account.address), - account.active.plus(account.pending), - delta - ) - debugLog(`Checking nonvoting invariant for ${account.address}`) - assertAlmostEqualBN( - await mockLockedGold.nonvotingAccountBalance(account.address), - account.nonvoting, - delta - ) - } - - const checkGroupInvariants = async (vAccounts: Account[], delta: number = 0) => { - const pendingTotal = vAccounts.reduce((a, b) => a.plus(b.pending), new BigNumber(0)) - const activeTotal = vAccounts.reduce((a, b) => a.plus(b.active), new BigNumber(0)) - debugLog(`Checking pending vote invariant for group`) - assertEqualBN(await election.getPendingVotesForGroup(group), pendingTotal) - debugLog(`Checking active vote invariant for group`) - assertAlmostEqualBN(await election.getActiveVotesForGroup(group), activeTotal, delta) - debugLog(`Checking total vote invariant for group`) - assertEqualBN( - await election.getTotalVotesForGroup(group), - pendingTotal.plus(await election.getActiveVotesForGroup(group)) - ) - assertEqualBN(await election.getTotalVotes(), await election.getTotalVotesForGroup(group)) - } - - const revokeAllAndCheckInvariants = async (delta: number = 0) => { - const vAccounts = await Promise.all( - voters.map(async (v) => { - return { - address: v, - active: await election.getActiveVotesForGroupByAccount(group, v), - pending: await election.getPendingVotesForGroupByAccount(group, v), - nonvoting: await mockLockedGold.nonvotingAccountBalance(v), - } - }) - ) - - for (const account of vAccounts) { - await checkVoterInvariants(account, delta) - const address = account.address - // Need to fetch actual number due to potential rounding errors. - const active = await election.getActiveVotesForGroupByAccount(group, address) - if (active.gt(0)) { - await election.revokeActive(group, active.toFixed(), NULL_ADDRESS, NULL_ADDRESS, 0, { - from: address, - }) - account.active = new BigNumber(0) - account.nonvoting = account.nonvoting.plus(active) - } - const pending = account.pending - if (pending.gt(0)) { - await election.revokePending(group, pending.toFixed(), NULL_ADDRESS, NULL_ADDRESS, 0, { - from: address, - }) - account.pending = new BigNumber(0) - account.nonvoting = account.nonvoting.plus(pending) - } - assertEqualBN(await election.getActiveVotesForGroupByAccount(group, address), 0) - assertEqualBN(await election.getPendingVotesForGroupByAccount(group, address), 0) - assertEqualBN(await mockLockedGold.nonvotingAccountBalance(address), account.nonvoting) - } - } - - let voterAccounts: Account[] - beforeEach(async () => { - // 50M gives us 450M total locked gold - const voterStartBalance = new BigNumber(web3.utils.toWei('50000000')) - await mockValidators.setMembers(group, [accounts[9]]) - await registry.setAddressFor(CeloContractName.Validators, accounts[0]) - await election.markGroupEligible(group, NULL_ADDRESS, NULL_ADDRESS) - await registry.setAddressFor(CeloContractName.Validators, mockValidators.address) - await mockLockedGold.setTotalLockedGold(voterStartBalance.times(voters.length)) - await mockValidators.setNumRegisteredValidators(1) - await Promise.all( - voters.map((voter) => - mockLockedGold.incrementNonvotingAccountBalance(voter, voterStartBalance) - ) - ) - voterAccounts = voters.map((v) => { - return { - address: v, - nonvoting: voterStartBalance, - pending: new BigNumber(0), - active: new BigNumber(0), - } - }) - }) - - describe('when placing, activating, and revoking votes randomly', function (this: any) { - this.timeout(0) - describe('when no epoch rewards are distributed', () => { - it('actual and expected should always match exactly', async () => { - for (let i = 0; i < 10; i++) { - voterAccounts = await Promise.all(voterAccounts.map(makeRandomAction)) - await Promise.all(voterAccounts.map(checkVoterInvariants)) - await checkGroupInvariants(voterAccounts) - await mineBlocks(EPOCH, web3) - } - await revokeAllAndCheckInvariants() - }) - }) - - describe('when epoch rewards are distributed', () => { - it('actual and expected should always match within a small delta', async () => { - const distributeEpochRewards = async (vAccounts: Account[]) => { - // 1% compounded 100x gives up to a 2.7x multiplier. - const reward = randomInteger((await election.getTotalVotes()).times(0.01).dp(0)) - const activeTotal = vAccounts.reduce((a, b) => a.plus(b.active), new BigNumber(0)) - if (!reward.isZero() && !activeTotal.isZero()) { - debugLog(`Distributing ${reward.toFixed()} in rewards to voters`) - await election.distributeEpochRewards( - group, - reward.toFixed(), - NULL_ADDRESS, - NULL_ADDRESS - ) - // tslint:disable-next-line - for (let i = 0; i < vAccounts.length; i++) { - vAccounts[i].active = activeTotal - .plus(reward) - .times(vAccounts[i].active) - .div(activeTotal) - .dp(0) - await printAccount(vAccounts[i]) - } - } - return vAccounts - } - - for (let i = 0; i < 30; i++) { - debugLog(`Starting iteration ${i}`) - voterAccounts = await Promise.all(voterAccounts.map(makeRandomAction)) - await Promise.all(voterAccounts.map((v) => checkVoterInvariants(v, 10))) - await checkGroupInvariants(voterAccounts, 10) - - await mineBlocks(EPOCH, web3) - voterAccounts = await distributeEpochRewards(voterAccounts) - await Promise.all(voterAccounts.map((v) => checkVoterInvariants(v, 10))) - await checkGroupInvariants(voterAccounts, 10) - } - await revokeAllAndCheckInvariants(10) - }) - }) - }) - }) -}) diff --git a/packages/protocol/test/governance/voting/release_gold.ts b/packages/protocol/test/governance/voting/release_gold.ts deleted file mode 100644 index 513cede5e..000000000 --- a/packages/protocol/test/governance/voting/release_gold.ts +++ /dev/null @@ -1,2247 +0,0 @@ -import { NULL_ADDRESS } from '@celo/base/lib/address' -import { CeloContractName } from '@celo/protocol/lib/registry-utils' -import { getParsedSignatureOfAddress } from '@celo/protocol/lib/signing-utils' -import { - assertEqualBN, - assertGteBN, - assertLogMatches, - assertSameAddress, - // tslint:disable-next-line: ordered-imports - assertTransactionRevertWithReason, - assertTransactionRevertWithoutReason, - expectBigNumberInRange, - timeTravel, -} from '@celo/protocol/lib/test-utils' -// tslint:disable-next-line: ordered-imports -import { Signature, addressToPublicKey } from '@celo/utils/lib/signatureUtils' -import { BigNumber } from 'bignumber.js' -import _ from 'lodash' -import { - AccountsContract, - AccountsInstance, - FreezerContract, - FreezerInstance, - GoldTokenContract, - GoldTokenInstance, - LockedGoldContract, - LockedGoldInstance, - MockElectionContract, - MockElectionInstance, - MockGovernanceContract, - MockGovernanceInstance, - MockStableTokenContract, - MockStableTokenInstance, - MockValidatorsContract, - MockValidatorsInstance, - RegistryContract, - RegistryInstance, - ReleaseGoldContract, - ReleaseGoldInstance, -} from 'types' -import Web3 from 'web3' - -const ONE_GOLDTOKEN = new BigNumber('1000000000000000000') - -const authorizationTests: any = {} -const authorizationTestDescriptions = { - voting: { - me: 'vote signing key', - subject: 'voteSigner', - }, - validating: { - me: 'validating signing key', - subject: 'validatorSigner', - }, - attestation: { - me: 'attestation signing key', - subject: 'attestationSigner', - }, -} - -const isTest = true - -interface ReleaseGoldConfig { - releaseStartTime: number - releaseCliffTime: number - numReleasePeriods: number - releasePeriod: number - amountReleasedPerPeriod: BigNumber - revocable: boolean - beneficiary: string - releaseOwner: string - refundAddress: string - subjectToLiquidityProvision: boolean - initialDistributionRatio: number - canValidate: boolean - canVote: boolean -} - -const Accounts: AccountsContract = artifacts.require('Accounts') -const Freezer: FreezerContract = artifacts.require('Freezer') -const GoldToken: GoldTokenContract = artifacts.require('GoldToken') -const LockedGold: LockedGoldContract = artifacts.require('LockedGold') -const MockStableToken: MockStableTokenContract = artifacts.require('MockStableToken') -const MockElection: MockElectionContract = artifacts.require('MockElection') -const MockGovernance: MockGovernanceContract = artifacts.require('MockGovernance') -const MockValidators: MockValidatorsContract = artifacts.require('MockValidators') -const Registry: RegistryContract = artifacts.require('Registry') -const ReleaseGold: ReleaseGoldContract = artifacts.require('ReleaseGold') - -// @ts-ignore -// TODO(mcortesi): Use BN -LockedGold.numberFormat = 'BigNumber' -// @ts-ignore -ReleaseGold.numberFormat = 'BigNumber' -// @ts-ignore -MockStableToken.numberFormat = 'BigNumber' -// @ts-ignore -GoldToken.numberFormat = 'BigNumber' - -const MINUTE = 60 -const HOUR = 60 * 60 -const DAY = 24 * HOUR -const MONTH = 30 * DAY -const UNLOCKING_PERIOD = 3 * DAY - -contract('ReleaseGold', (accounts: string[]) => { - const owner = accounts[0] - const beneficiary = accounts[1] - const walletAddress = beneficiary - - const releaseOwner = accounts[2] - const refundAddress = accounts[3] - const newBeneficiary = accounts[4] - let accountsInstance: AccountsInstance - let freezerInstance: FreezerInstance - let goldTokenInstance: GoldTokenInstance - let lockedGoldInstance: LockedGoldInstance - let mockElection: MockElectionInstance - let mockGovernance: MockGovernanceInstance - let mockValidators: MockValidatorsInstance - let mockStableToken: MockStableTokenInstance - let registry: RegistryInstance - let releaseGoldInstance: ReleaseGoldInstance - let proofOfWalletOwnership: Signature - const TOTAL_AMOUNT = ONE_GOLDTOKEN.times(10) - - const releaseGoldDefaultSchedule: ReleaseGoldConfig = { - releaseStartTime: null, // To be adjusted on every run - releaseCliffTime: HOUR, - numReleasePeriods: 4, - releasePeriod: 3 * MONTH, - amountReleasedPerPeriod: TOTAL_AMOUNT.div(4), - revocable: true, - beneficiary, - releaseOwner, - refundAddress, - subjectToLiquidityProvision: false, - initialDistributionRatio: 1000, // No distribution limit - canVote: true, - canValidate: false, - } - - const createNewReleaseGoldInstance = async ( - releaseGoldSchedule: ReleaseGoldConfig, - web3: Web3, - override = { - prefund: true, - startReleasing: false, - } - ) => { - const startDelay = 5 * MINUTE - releaseGoldSchedule.releaseStartTime = (await getCurrentBlockchainTimestamp(web3)) + startDelay - releaseGoldInstance = await ReleaseGold.new(isTest) - if (override.prefund) { - await goldTokenInstance.transfer( - releaseGoldInstance.address, - releaseGoldSchedule.amountReleasedPerPeriod.multipliedBy( - releaseGoldSchedule.numReleasePeriods - ), - { - from: owner, - } - ) - } - await releaseGoldInstance.initialize( - releaseGoldSchedule.releaseStartTime, - releaseGoldSchedule.releaseCliffTime, - releaseGoldSchedule.numReleasePeriods, - releaseGoldSchedule.releasePeriod, - releaseGoldSchedule.amountReleasedPerPeriod, - releaseGoldSchedule.revocable, - releaseGoldSchedule.beneficiary, - releaseGoldSchedule.releaseOwner, - releaseGoldSchedule.refundAddress, - releaseGoldSchedule.subjectToLiquidityProvision, - releaseGoldSchedule.initialDistributionRatio, - releaseGoldSchedule.canValidate, - releaseGoldSchedule.canVote, - registry.address, - { from: owner } - ) - if (override.startReleasing) { - await timeTravel( - startDelay + releaseGoldSchedule.releaseCliffTime + releaseGoldSchedule.releasePeriod, - web3 - ) - } - } - - const getCurrentBlockchainTimestamp = (web3: Web3): Promise => - web3.eth.getBlock('latest').then((block) => Number(block.timestamp)) - - beforeEach(async () => { - accountsInstance = await Accounts.new(true) - freezerInstance = await Freezer.new(true) - goldTokenInstance = await GoldToken.new(true) - lockedGoldInstance = await LockedGold.new(true) - mockElection = await MockElection.new() - mockGovernance = await MockGovernance.new() - mockValidators = await MockValidators.new() - mockStableToken = await MockStableToken.new() - - registry = await Registry.new(true) - await registry.setAddressFor(CeloContractName.Accounts, accountsInstance.address) - await registry.setAddressFor(CeloContractName.Election, mockElection.address) - await registry.setAddressFor(CeloContractName.Freezer, freezerInstance.address) - await registry.setAddressFor(CeloContractName.GoldToken, goldTokenInstance.address) - await registry.setAddressFor(CeloContractName.Governance, mockGovernance.address) - await registry.setAddressFor(CeloContractName.LockedGold, lockedGoldInstance.address) - await registry.setAddressFor(CeloContractName.Validators, mockValidators.address) - await registry.setAddressFor(CeloContractName.StableToken, mockStableToken.address) - await lockedGoldInstance.initialize(registry.address, UNLOCKING_PERIOD) - await goldTokenInstance.initialize(registry.address) - await accountsInstance.initialize(registry.address) - await accountsInstance.createAccount({ from: beneficiary }) - }) - - describe('#initialize', () => { - it('should indicate isFunded() if deployment is prefunded', async () => { - await createNewReleaseGoldInstance(releaseGoldDefaultSchedule, web3, { - prefund: true, - startReleasing: false, - }) - const isFunded = await releaseGoldInstance.isFunded() - assert.isTrue(isFunded) - }) - - it('should not indicate isFunded() (and not revert) if deployment is not prefunded', async () => { - await createNewReleaseGoldInstance(releaseGoldDefaultSchedule, web3, { - prefund: false, - startReleasing: false, - }) - const isFunded = await releaseGoldInstance.isFunded() - assert.isFalse(isFunded) - }) - }) - - describe('#payable', () => { - it('should accept gold transfer by default from anyone', async () => { - await createNewReleaseGoldInstance(releaseGoldDefaultSchedule, web3) - await goldTokenInstance.transfer(releaseGoldInstance.address, ONE_GOLDTOKEN.times(2), { - from: accounts[8], - }) - }) - - it('should not update isFunded() if schedule principle not fulfilled', async () => { - await createNewReleaseGoldInstance(releaseGoldDefaultSchedule, web3, { - prefund: false, - startReleasing: false, - }) - const insufficientPrinciple = releaseGoldDefaultSchedule.amountReleasedPerPeriod - .multipliedBy(releaseGoldDefaultSchedule.numReleasePeriods) - .minus(1) - await goldTokenInstance.transfer(releaseGoldInstance.address, insufficientPrinciple, { - from: owner, - }) - const isFunded = await releaseGoldInstance.isFunded() - assert.isFalse(isFunded) - }) - - it('should update isFunded() if schedule principle is fulfilled after deployment', async () => { - await createNewReleaseGoldInstance(releaseGoldDefaultSchedule, web3, { - prefund: false, - startReleasing: false, - }) - const sufficientPrinciple = releaseGoldDefaultSchedule.amountReleasedPerPeriod.multipliedBy( - releaseGoldDefaultSchedule.numReleasePeriods - ) - await goldTokenInstance.transfer(releaseGoldInstance.address, sufficientPrinciple, { - from: owner, - }) - const isFunded = await releaseGoldInstance.isFunded() - assert.isTrue(isFunded) - }) - - it('should update isFunded() if schedule principle not fulfilled but has begun releasing', async () => { - await createNewReleaseGoldInstance(releaseGoldDefaultSchedule, web3, { - prefund: false, - startReleasing: true, - }) - const insufficientPrinciple = releaseGoldDefaultSchedule.amountReleasedPerPeriod - .multipliedBy(releaseGoldDefaultSchedule.numReleasePeriods) - .minus(1) - await goldTokenInstance.transfer(releaseGoldInstance.address, insufficientPrinciple, { - from: owner, - }) - const isFunded = await releaseGoldInstance.isFunded() - assert.isTrue(isFunded) - }) - }) - - describe('#transfer', () => { - const receiver = accounts[5] - const transferAmount = 10 - - beforeEach(async () => { - await createNewReleaseGoldInstance(releaseGoldDefaultSchedule, web3) - await mockStableToken.mint(releaseGoldInstance.address, transferAmount) - }) - - it('should transfer stable token from the release gold instance', async () => { - await releaseGoldInstance.transfer(receiver, transferAmount, { from: beneficiary }) - const contractBalance = await mockStableToken.balanceOf(releaseGoldInstance.address) - const recipientBalance = await mockStableToken.balanceOf(receiver) - assertEqualBN(contractBalance, 0) - assertEqualBN(recipientBalance, transferAmount) - }) - }) - - describe('#genericTransfer', () => { - const receiver = accounts[5] - const transferAmount = 10 - - beforeEach(async () => { - await createNewReleaseGoldInstance(releaseGoldDefaultSchedule, web3) - await mockStableToken.mint(releaseGoldInstance.address, transferAmount) - }) - - it('should transfer stable token from the release gold instance', async () => { - const startBalanceFrom = await mockStableToken.balanceOf(releaseGoldInstance.address) - const startBalanceTo = await mockStableToken.balanceOf(receiver) - await releaseGoldInstance.genericTransfer(mockStableToken.address, receiver, transferAmount, { - from: beneficiary, - }) - const endBalanceFrom = await mockStableToken.balanceOf(releaseGoldInstance.address) - const endBalanceTo = await mockStableToken.balanceOf(receiver) - assertEqualBN(endBalanceFrom, startBalanceFrom.minus(transferAmount)) - assertEqualBN(endBalanceTo, startBalanceTo.plus(transferAmount)) - }) - - it('should emit safeTransfer logs on erc20 revert', async () => { - const startBalanceFrom = await mockStableToken.balanceOf(releaseGoldInstance.address) - await assertTransactionRevertWithReason( - releaseGoldInstance.genericTransfer( - mockStableToken.address, - receiver, - startBalanceFrom.plus(1), - { - from: beneficiary, - } - ), - 'SafeERC20: ERC20 operation did not succeed' - ) - }) - - it('should revert when attempting transfer of goldtoken from the release gold instance', async () => { - await assertTransactionRevertWithReason( - releaseGoldInstance.genericTransfer(goldTokenInstance.address, receiver, transferAmount, { - from: beneficiary, - }), - 'Transfer must not target celo balance' - ) - }) - }) - - describe('#creation', () => { - describe('when an instance is properly created', () => { - beforeEach(async () => { - await createNewReleaseGoldInstance(releaseGoldDefaultSchedule, web3) - }) - - it('should have associated funds with a schedule upon creation', async () => { - const allocatedFunds = await goldTokenInstance.balanceOf(releaseGoldInstance.address) - assertEqualBN( - allocatedFunds, - new BigNumber(releaseGoldDefaultSchedule.numReleasePeriods).multipliedBy( - releaseGoldDefaultSchedule.amountReleasedPerPeriod - ) - ) - }) - - it('should set a beneficiary to releaseGold instance', async () => { - const releaseGoldBeneficiary = await releaseGoldInstance.beneficiary() - assert.equal(releaseGoldBeneficiary, releaseGoldDefaultSchedule.beneficiary) - }) - - it('should set a releaseOwner to releaseGold instance', async () => { - const releaseGoldOwner = await releaseGoldInstance.releaseOwner() - assert.equal(releaseGoldOwner, releaseGoldDefaultSchedule.releaseOwner) - }) - - it('should set releaseGold number of periods to releaseGold instance', async () => { - const [, , releaseGoldNumPeriods, ,] = await releaseGoldInstance.releaseSchedule() - assertEqualBN(releaseGoldNumPeriods, releaseGoldDefaultSchedule.numReleasePeriods) - }) - - it('should set releaseGold amount per period to releaseGold instance', async () => { - const [, , , , releasedAmountPerPeriod] = await releaseGoldInstance.releaseSchedule() - assertEqualBN(releasedAmountPerPeriod, releaseGoldDefaultSchedule.amountReleasedPerPeriod) - }) - - it('should set releaseGold period to releaseGold instance', async () => { - const [, , , releaseGoldPeriodSec] = await releaseGoldInstance.releaseSchedule() - assertEqualBN(releaseGoldPeriodSec, releaseGoldDefaultSchedule.releasePeriod) - }) - - it('should set releaseGold start time to releaseGold instance', async () => { - const [releaseGoldStartTime, , , ,] = await releaseGoldInstance.releaseSchedule() - assertEqualBN(releaseGoldStartTime, releaseGoldDefaultSchedule.releaseStartTime) - }) - - it('should set releaseGold cliff to releaseGold instance', async () => { - const [, releaseGoldCliffStartTime, , ,] = await releaseGoldInstance.releaseSchedule() - const releaseGoldCliffStartTimeComputed = new BigNumber( - releaseGoldDefaultSchedule.releaseStartTime - ).plus(releaseGoldDefaultSchedule.releaseCliffTime) - assertEqualBN(releaseGoldCliffStartTime, releaseGoldCliffStartTimeComputed) - }) - - it('should set revocable flag to releaseGold instance', async () => { - const [releaseGoldRevocable, , ,] = await releaseGoldInstance.revocationInfo() - assert.equal(releaseGoldRevocable, releaseGoldDefaultSchedule.revocable) - }) - - it('should set releaseOwner to releaseGold instance', async () => { - const releaseGoldOwner = await releaseGoldInstance.releaseOwner() - assert.equal(releaseGoldOwner, releaseGoldDefaultSchedule.releaseOwner) - }) - - it('should set liquidity provision met to true', async () => { - const liquidityProvisionMet = await releaseGoldInstance.liquidityProvisionMet() - assert.equal(liquidityProvisionMet, true) - }) - - it('should have zero total withdrawn on init', async () => { - const totalWithdrawn = await releaseGoldInstance.totalWithdrawn() - assertEqualBN(totalWithdrawn, 0) - }) - - it('should be unrevoked on init and have revoke time equal zero', async () => { - const isRevoked = await releaseGoldInstance.isRevoked() - assert.equal(isRevoked, false) - const [, , , revokeTime] = await releaseGoldInstance.revocationInfo() - assertEqualBN(revokeTime, 0) - }) - - it('should have releaseGoldBalanceAtRevoke on init equal to zero', async () => { - const [, , releasedBalanceAtRevoke] = await releaseGoldInstance.revocationInfo() - assertEqualBN(releasedBalanceAtRevoke, 0) - }) - - it('should revert when releaseGold beneficiary is the null address', async () => { - const releaseGoldSchedule = _.clone(releaseGoldDefaultSchedule) - releaseGoldSchedule.beneficiary = NULL_ADDRESS - await assertTransactionRevertWithReason( - createNewReleaseGoldInstance(releaseGoldSchedule, web3), - 'The release schedule beneficiary cannot be the zero addresss' - ) - }) - - it('should revert when releaseGold periods are zero', async () => { - const releaseGoldSchedule = _.clone(releaseGoldDefaultSchedule) - releaseGoldSchedule.numReleasePeriods = 0 - await assertTransactionRevertWithReason( - createNewReleaseGoldInstance(releaseGoldSchedule, web3), - 'There must be at least one releasing period' - ) - }) - - it('should revert when released amount per period is zero', async () => { - const releaseGoldSchedule = _.clone(releaseGoldDefaultSchedule) - releaseGoldSchedule.amountReleasedPerPeriod = new BigNumber('0') - await assertTransactionRevertWithReason( - createNewReleaseGoldInstance(releaseGoldSchedule, web3), - 'The released amount per period must be greater than zero' - ) - }) - - it('should overflow for very large combinations of release periods and amount per time', async () => { - const releaseGoldSchedule = _.clone(releaseGoldDefaultSchedule) - releaseGoldSchedule.numReleasePeriods = Number.MAX_SAFE_INTEGER - releaseGoldSchedule.amountReleasedPerPeriod = new BigNumber(2).pow(300) - await assertTransactionRevertWithReason( - createNewReleaseGoldInstance(releaseGoldSchedule, web3), - 'value out-of-bounds' - ) - }) - }) - }) - - describe('#setBeneficiary', () => { - beforeEach(async () => { - await createNewReleaseGoldInstance(releaseGoldDefaultSchedule, web3) - }) - - it('should set a new beneficiary as the old beneficiary', async () => { - await releaseGoldInstance.setBeneficiary(newBeneficiary, { from: owner }) - const actualBeneficiary = await releaseGoldInstance.beneficiary() - assertSameAddress(actualBeneficiary, newBeneficiary) - }) - - it('should revert when setting a new beneficiary from the release owner', async () => { - await assertTransactionRevertWithReason( - releaseGoldInstance.setBeneficiary(newBeneficiary, { from: releaseOwner }), - 'Ownable: caller is not the owner' - ) - }) - - it('should emit the BeneficiarySet event', async () => { - const setNewBeneficiaryTx = await releaseGoldInstance.setBeneficiary(newBeneficiary, { - from: owner, - }) - assertLogMatches(setNewBeneficiaryTx.logs[0], 'BeneficiarySet', { - beneficiary: newBeneficiary, - }) - }) - }) - - describe('#createAccount', () => { - beforeEach(async () => { - await createNewReleaseGoldInstance(releaseGoldDefaultSchedule, web3) - }) - - describe('when unrevoked', () => { - it('creates the account by beneficiary', async () => { - let isAccount = await accountsInstance.isAccount(releaseGoldInstance.address) - assert.isFalse(isAccount) - await releaseGoldInstance.createAccount({ from: beneficiary }) - isAccount = await accountsInstance.isAccount(releaseGoldInstance.address) - assert.isTrue(isAccount) - }) - - it('reverts if a non-beneficiary attempts account creation', async () => { - const isAccount = await accountsInstance.isAccount(releaseGoldInstance.address) - assert.isFalse(isAccount) - await assertTransactionRevertWithReason( - releaseGoldInstance.createAccount({ from: accounts[2] }), - 'Sender must be the beneficiary and state must not be revoked' - ) - }) - }) - - describe('when revoked', () => { - beforeEach(async () => { - await releaseGoldInstance.revoke({ from: releaseOwner }) - }) - - it('reverts if anyone attempts account creation', async () => { - const isAccount = await accountsInstance.isAccount(releaseGoldInstance.address) - assert.isFalse(isAccount) - await assertTransactionRevertWithReason( - releaseGoldInstance.createAccount({ from: beneficiary }), - 'Sender must be the beneficiary and state must not be revoked' - ) - }) - }) - }) - - describe('#setAccount', () => { - const accountName = 'name' - const dataEncryptionKey: any = - '0x02f2f48ee19680706196e2e339e5da3491186e0c4c5030670656b0e01611111111' - - beforeEach(async () => { - await createNewReleaseGoldInstance(releaseGoldDefaultSchedule, web3) - proofOfWalletOwnership = await getParsedSignatureOfAddress( - web3, - releaseGoldInstance.address, - beneficiary - ) - }) - - describe('when unrevoked', () => { - it('sets the account by beneficiary', async () => { - let isAccount = await accountsInstance.isAccount(releaseGoldInstance.address) - assert.isFalse(isAccount) - await releaseGoldInstance.setAccount( - accountName, - dataEncryptionKey, - walletAddress, - proofOfWalletOwnership.v, - proofOfWalletOwnership.r, - proofOfWalletOwnership.s, - { - from: beneficiary, - } - ) - isAccount = await accountsInstance.isAccount(releaseGoldInstance.address) - assert.isTrue(isAccount) - }) - - it('reverts if a non-beneficiary attempts to set the account', async () => { - const isAccount = await accountsInstance.isAccount(releaseGoldInstance.address) - assert.isFalse(isAccount) - await assertTransactionRevertWithReason( - releaseGoldInstance.setAccount( - accountName, - dataEncryptionKey, - walletAddress, - proofOfWalletOwnership.v, - proofOfWalletOwnership.r, - proofOfWalletOwnership.s, - { - from: accounts[2], - } - ), - 'Sender must be the beneficiary and state must not be revoked' - ) - }) - - it('should set the name, dataEncryptionKey and walletAddress of the account by beneficiary', async () => { - let isAccount = await accountsInstance.isAccount(releaseGoldInstance.address) - assert.isFalse(isAccount) - await releaseGoldInstance.setAccount( - accountName, - dataEncryptionKey, - walletAddress, - proofOfWalletOwnership.v, - proofOfWalletOwnership.r, - proofOfWalletOwnership.s, - { - from: beneficiary, - } - ) - isAccount = await accountsInstance.isAccount(releaseGoldInstance.address) - assert.isTrue(isAccount) - const expectedWalletAddress = await accountsInstance.getWalletAddress( - releaseGoldInstance.address - ) - assert.equal(expectedWalletAddress, walletAddress) - // @ts-ignore - const expectedKey: string = await accountsInstance.getDataEncryptionKey( - releaseGoldInstance.address - ) - assert.equal(expectedKey, dataEncryptionKey) - const expectedName = await accountsInstance.getName(releaseGoldInstance.address) - assert.equal(expectedName, accountName) - }) - - it('should revert to set the name, dataEncryptionKey and walletAddress of the account by a non-beneficiary', async () => { - const isAccount = await accountsInstance.isAccount(releaseGoldInstance.address) - assert.isFalse(isAccount) - await assertTransactionRevertWithReason( - releaseGoldInstance.setAccount( - accountName, - dataEncryptionKey, - walletAddress, - proofOfWalletOwnership.v, - proofOfWalletOwnership.r, - proofOfWalletOwnership.s, - { - from: releaseOwner, - } - ), - 'Sender must be the beneficiary and state must not be revoked' - ) - }) - }) - - describe('when revoked', () => { - beforeEach(async () => { - await releaseGoldInstance.revoke({ from: releaseOwner }) - }) - - it('reverts if anyone attempts to set the account', async () => { - const isAccount = await accountsInstance.isAccount(releaseGoldInstance.address) - assert.isFalse(isAccount) - await assertTransactionRevertWithReason( - releaseGoldInstance.setAccount( - accountName, - dataEncryptionKey, - walletAddress, - proofOfWalletOwnership.v, - proofOfWalletOwnership.r, - proofOfWalletOwnership.s, - { - from: releaseOwner, - } - ), - 'Sender must be the beneficiary and state must not be revoked' - ) - }) - - it('should revert to set the name, dataEncryptionKey and walletAddress of the account', async () => { - const isAccount = await accountsInstance.isAccount(releaseGoldInstance.address) - assert.isFalse(isAccount) - await assertTransactionRevertWithReason( - releaseGoldInstance.setAccount( - accountName, - dataEncryptionKey, - walletAddress, - proofOfWalletOwnership.v, - proofOfWalletOwnership.r, - proofOfWalletOwnership.s, - { - from: releaseOwner, - } - ), - 'Sender must be the beneficiary and state must not be revoked' - ) - }) - }) - }) - - describe('#setAccountName', () => { - const accountName = 'name' - - beforeEach(async () => { - await createNewReleaseGoldInstance(releaseGoldDefaultSchedule, web3) - }) - - describe('when the account has not been created', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - releaseGoldInstance.setAccountName(accountName, { from: beneficiary }), - 'Register with createAccount to set account name' - ) - }) - }) - - describe('when the account has been created', () => { - beforeEach(async () => { - await releaseGoldInstance.createAccount({ from: beneficiary }) - }) - - describe('when unrevoked', () => { - it('beneficiary should set the name', async () => { - await releaseGoldInstance.setAccountName(accountName, { from: beneficiary }) - const result = await accountsInstance.getName(releaseGoldInstance.address) - assert.equal(result, accountName) - }) - - it('should revert if non-beneficiary attempts to set the name', async () => { - await assertTransactionRevertWithReason( - releaseGoldInstance.setAccountName(accountName, { from: accounts[2] }), - 'Sender must be the beneficiary and state must not be revoked' - ) - }) - }) - - describe('when revoked', () => { - beforeEach(async () => { - await releaseGoldInstance.revoke({ from: releaseOwner }) - }) - - it('should revert if anyone attempts to set the name', async () => { - await assertTransactionRevertWithReason( - releaseGoldInstance.setAccountName(accountName, { from: releaseOwner }), - 'Sender must be the beneficiary and state must not be revoked' - ) - }) - }) - }) - }) - - describe('#setAccountWalletAddress', () => { - beforeEach(async () => { - await createNewReleaseGoldInstance(releaseGoldDefaultSchedule, web3) - proofOfWalletOwnership = await getParsedSignatureOfAddress( - web3, - releaseGoldInstance.address, - beneficiary - ) - }) - - describe('when the releaseGold account has not been created', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - releaseGoldInstance.setAccountWalletAddress( - walletAddress, - proofOfWalletOwnership.v, - proofOfWalletOwnership.r, - proofOfWalletOwnership.s, - { from: beneficiary } - ), - 'Unknown account' - ) - }) - }) - - describe('when the account has been created', () => { - beforeEach(async () => { - await releaseGoldInstance.createAccount({ from: beneficiary }) - }) - - describe('when unrevoked', () => { - it('beneficiary should set the walletAddress', async () => { - await releaseGoldInstance.setAccountWalletAddress( - walletAddress, - proofOfWalletOwnership.v, - proofOfWalletOwnership.r, - proofOfWalletOwnership.s, - { from: beneficiary } - ) - const result = await accountsInstance.getWalletAddress(releaseGoldInstance.address) - assert.equal(result, walletAddress) - }) - - it('should revert if non-beneficiary attempts to set the walletAddress', async () => { - await assertTransactionRevertWithReason( - releaseGoldInstance.setAccountWalletAddress( - walletAddress, - proofOfWalletOwnership.v, - proofOfWalletOwnership.r, - proofOfWalletOwnership.s, - { from: accounts[2] } - ), - 'Sender must be the beneficiary and state must not be revoked' - ) - }) - - it('beneficiary should set the NULL_ADDRESS', async () => { - await releaseGoldInstance.setAccountWalletAddress(NULL_ADDRESS, '0x0', '0x0', '0x0', { - from: beneficiary, - }) - const result = await accountsInstance.getWalletAddress(releaseGoldInstance.address) - assert.equal(result, NULL_ADDRESS) - }) - }) - - describe('when revoked', () => { - beforeEach(async () => { - await releaseGoldInstance.revoke({ from: releaseOwner }) - }) - - it('should revert if anyone attempts to set the walletAddress', async () => { - await assertTransactionRevertWithReason( - releaseGoldInstance.setAccountWalletAddress( - walletAddress, - proofOfWalletOwnership.v, - proofOfWalletOwnership.r, - proofOfWalletOwnership.s, - { from: releaseOwner } - ), - 'Sender must be the beneficiary and state must not be revoked' - ) - }) - }) - }) - }) - - describe('#setAccountMetadataURL', () => { - const metadataURL = 'meta' - - beforeEach(async () => { - await createNewReleaseGoldInstance(releaseGoldDefaultSchedule, web3) - }) - - describe('when the account has not been created', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - releaseGoldInstance.setAccountMetadataURL(metadataURL, { from: beneficiary }), - 'Unknown account' - ) - }) - }) - - describe('when the account has been created', () => { - beforeEach(async () => { - await releaseGoldInstance.createAccount({ from: beneficiary }) - }) - - describe('when unrevoked', () => { - it('only beneficiary should set the metadataURL', async () => { - await releaseGoldInstance.setAccountMetadataURL(metadataURL, { from: beneficiary }) - const result = await accountsInstance.getMetadataURL(releaseGoldInstance.address) - assert.equal(result, metadataURL) - }) - - it('should revert if non-beneficiary attempts to set the metadataURL', async () => { - await assertTransactionRevertWithReason( - releaseGoldInstance.setAccountMetadataURL(metadataURL, { from: accounts[2] }), - 'Sender must be the beneficiary and state must not be revoked' - ) - }) - }) - - describe('when revoked', () => { - beforeEach(async () => { - await releaseGoldInstance.revoke({ from: releaseOwner }) - }) - - it('should revert if anyone attempts to set the metadataURL', async () => { - await assertTransactionRevertWithReason( - releaseGoldInstance.setAccountMetadataURL(metadataURL, { from: releaseOwner }), - 'Sender must be the beneficiary and state must not be revoked' - ) - }) - }) - }) - }) - - describe('#setAccountDataEncryptionKey', () => { - const dataEncryptionKey: any = - '0x02f2f48ee19680706196e2e339e5da3491186e0c4c5030670656b0e01611111111' - const longDataEncryptionKey: any = - '0x04f2f48ee19680706196e2e339e5da3491186e0c4c5030670656b0e01611111111' + - '02f2f48ee19680706196e2e339e5da3491186e0c4c5030670656b0e01611111111' - - beforeEach(async () => { - await createNewReleaseGoldInstance(releaseGoldDefaultSchedule, web3) - await releaseGoldInstance.createAccount({ from: beneficiary }) - }) - - it('beneficiary should set dataEncryptionKey', async () => { - await releaseGoldInstance.setAccountDataEncryptionKey(dataEncryptionKey, { - from: beneficiary, - }) - // @ts-ignore - const fetchedKey: string = await accountsInstance.getDataEncryptionKey( - releaseGoldInstance.address - ) - assert.equal(fetchedKey, dataEncryptionKey) - }) - - it('should revert if non-beneficiary attempts to set dataEncryptionKey', async () => { - await assertTransactionRevertWithReason( - releaseGoldInstance.setAccountDataEncryptionKey(dataEncryptionKey, { from: accounts[2] }), - 'Sender must be the beneficiary and state must not be revoked' - ) - }) - - it('should allow setting a key with leading zeros', async () => { - const keyWithZeros: any = - '0x00000000000000000000000000000000000000000000000f2f48ee19680706191111' - await releaseGoldInstance.setAccountDataEncryptionKey(keyWithZeros, { from: beneficiary }) - // @ts-ignore - const fetchedKey: string = await accountsInstance.getDataEncryptionKey( - releaseGoldInstance.address - ) - assert.equal(fetchedKey, keyWithZeros) - }) - - it('should revert when the key is invalid', async () => { - const invalidKey: any = '0x32132931293' - await assertTransactionRevertWithReason( - releaseGoldInstance.setAccountDataEncryptionKey(invalidKey, { from: beneficiary }), - 'data encryption key length <= 32' - ) - }) - - it('should allow a key that is longer than 33 bytes', async () => { - await releaseGoldInstance.setAccountDataEncryptionKey(longDataEncryptionKey, { - from: beneficiary, - }) - // @ts-ignore - const fetchedKey: string = await accountsInstance.getDataEncryptionKey( - releaseGoldInstance.address - ) - assert.equal(fetchedKey, longDataEncryptionKey) - }) - }) - - describe('#setMaxDistribution', () => { - beforeEach(async () => { - const releaseGoldSchedule = _.clone(releaseGoldDefaultSchedule) - releaseGoldSchedule.initialDistributionRatio = 0 - await createNewReleaseGoldInstance(releaseGoldSchedule, web3) - }) - - describe('when the max distribution is set to 50%', () => { - beforeEach(async () => { - await releaseGoldInstance.setMaxDistribution(500, { from: releaseOwner }) - }) - - it('should set max distribution to 5 gold', async () => { - const maxDistribution = await releaseGoldInstance.maxDistribution() - assertEqualBN(maxDistribution, TOTAL_AMOUNT.div(2)) - }) - }) - - describe('when the max distribution is set to 100%', () => { - beforeEach(async () => { - await releaseGoldInstance.setMaxDistribution(1000, { from: releaseOwner }) - }) - - it('should set max distribution to max uint256', async () => { - const maxDistribution = await releaseGoldInstance.maxDistribution() - assertGteBN(maxDistribution, TOTAL_AMOUNT) - }) - - it('cannot be lowered again', async () => { - await assertTransactionRevertWithReason( - releaseGoldInstance.setMaxDistribution(500, { from: releaseOwner }), - 'Cannot set max distribution lower if already set to 1000' - ) - }) - }) - }) - - describe('authorization tests:', () => { - Object.keys(authorizationTestDescriptions).forEach((key) => { - let authorizationTest: any - const authorized = accounts[4] // the account that is to be authorized for whatever role - let sig: any - - describe(`#authorize${_.upperFirst(authorizationTestDescriptions[key].subject)}()`, () => { - beforeEach(async () => { - const releaseGoldSchedule = _.clone(releaseGoldDefaultSchedule) - releaseGoldSchedule.revocable = false - releaseGoldSchedule.refundAddress = '0x0000000000000000000000000000000000000000' - releaseGoldSchedule.canValidate = true - await createNewReleaseGoldInstance(releaseGoldSchedule, web3) - await releaseGoldInstance.createAccount({ from: beneficiary }) - - authorizationTests.voting = { - fn: releaseGoldInstance.authorizeVoteSigner, - eventName: 'VoteSignerAuthorized', - getAuthorizedFromAccount: accountsInstance.getVoteSigner, - authorizedSignerToAccount: accountsInstance.voteSignerToAccount, - } - authorizationTests.validating = { - fn: releaseGoldInstance.authorizeValidatorSigner, - eventName: 'ValidatorSignerAuthorized', - getAuthorizedFromAccount: accountsInstance.getValidatorSigner, - authorizedSignerToAccount: accountsInstance.validatorSignerToAccount, - } - authorizationTests.attestation = { - fn: releaseGoldInstance.authorizeAttestationSigner, - eventName: 'AttestationSignerAuthorized', - getAuthorizedFromAccount: accountsInstance.getAttestationSigner, - authorizedSignerToAccount: accountsInstance.attestationSignerToAccount, - } - authorizationTest = authorizationTests[key] - sig = await getParsedSignatureOfAddress(web3, releaseGoldInstance.address, authorized) - }) - - it(`should set the authorized ${authorizationTestDescriptions[key].me}`, async () => { - await authorizationTest.fn(authorized, sig.v, sig.r, sig.s, { from: beneficiary }) - assert.equal(await accountsInstance.authorizedBy(authorized), releaseGoldInstance.address) - assert.equal( - await authorizationTest.getAuthorizedFromAccount(releaseGoldInstance.address), - authorized - ) - assert.equal( - await authorizationTest.authorizedSignerToAccount(authorized), - releaseGoldInstance.address - ) - }) - - // The attestations signer does not send txs. - if (authorizationTestDescriptions[key].subject !== 'attestationSigner') { - it(`should transfer 1 CELO to the ${authorizationTestDescriptions[key].me}`, async () => { - const balance1 = await web3.eth.getBalance(authorized) - await authorizationTest.fn(authorized, sig.v, sig.r, sig.s, { from: beneficiary }) - const balance2 = await web3.eth.getBalance(authorized) - assertEqualBN(new BigNumber(balance2).minus(balance1), web3.utils.toWei('1')) - }) - } else { - it(`should not transfer 1 CELO to the ${authorizationTestDescriptions[key].me}`, async () => { - const balance1 = await web3.eth.getBalance(authorized) - await authorizationTest.fn(authorized, sig.v, sig.r, sig.s, { from: beneficiary }) - const balance2 = await web3.eth.getBalance(authorized) - assertEqualBN(new BigNumber(balance2).minus(balance1), 0) - }) - } - - it(`should revert if the ${authorizationTestDescriptions[key].me} is an account`, async () => { - await accountsInstance.createAccount({ from: authorized }) - await assertTransactionRevertWithReason( - authorizationTest.fn(authorized, sig.v, sig.r, sig.s, { from: beneficiary }), - 'Cannot re-authorize address or locked gold account for another account' - ) - }) - - it(`should revert if the ${authorizationTestDescriptions[key].me} is already authorized`, async () => { - const otherAccount = accounts[5] - const otherSig = await getParsedSignatureOfAddress( - web3, - releaseGoldInstance.address, - otherAccount - ) - await accountsInstance.createAccount({ from: otherAccount }) - await assertTransactionRevertWithReason( - authorizationTest.fn(otherAccount, otherSig.v, otherSig.r, otherSig.s, { - from: beneficiary, - }), - 'Cannot re-authorize address or locked gold account for another account' - ) - }) - - it('should revert if the signature is incorrect', async () => { - const nonVoter = accounts[5] - const incorrectSig = await getParsedSignatureOfAddress( - web3, - releaseGoldInstance.address, - nonVoter - ) - await assertTransactionRevertWithReason( - authorizationTest.fn(authorized, incorrectSig.v, incorrectSig.r, incorrectSig.s, { - from: beneficiary, - }), - 'Invalid signature' - ) - }) - - describe('when a previous authorization has been made', () => { - const newAuthorized = accounts[6] - let balance1: string - let newSig: any - beforeEach(async () => { - await authorizationTest.fn(authorized, sig.v, sig.r, sig.s, { from: beneficiary }) - newSig = await getParsedSignatureOfAddress( - web3, - releaseGoldInstance.address, - newAuthorized - ) - balance1 = await web3.eth.getBalance(newAuthorized) - await authorizationTest.fn(newAuthorized, newSig.v, newSig.r, newSig.s, { - from: beneficiary, - }) - }) - - it(`should set the new authorized ${authorizationTestDescriptions[key].me}`, async () => { - assert.equal( - await accountsInstance.authorizedBy(newAuthorized), - releaseGoldInstance.address - ) - assert.equal( - await authorizationTest.getAuthorizedFromAccount(releaseGoldInstance.address), - newAuthorized - ) - assert.equal( - await authorizationTest.authorizedSignerToAccount(newAuthorized), - releaseGoldInstance.address - ) - }) - - it(`should not transfer 1 CELO to the ${authorizationTestDescriptions[key].me}`, async () => { - const balance2 = await web3.eth.getBalance(newAuthorized) - assertEqualBN(new BigNumber(balance2).minus(balance1), 0) - }) - - it('should preserve the previous authorization', async () => { - assert.equal( - await accountsInstance.authorizedBy(authorized), - releaseGoldInstance.address - ) - }) - }) - }) - }) - }) - - describe('#authorizeWithPublicKeys', () => { - const authorized = accounts[4] // the account that is to be authorized for whatever role - - describe('with ECDSA public key', () => { - beforeEach(async () => { - const releaseGoldSchedule = _.clone(releaseGoldDefaultSchedule) - releaseGoldSchedule.revocable = false - releaseGoldSchedule.canValidate = true - releaseGoldSchedule.refundAddress = NULL_ADDRESS - await createNewReleaseGoldInstance(releaseGoldSchedule, web3) - await releaseGoldInstance.createAccount({ from: beneficiary }) - const ecdsaPublicKey = await addressToPublicKey(authorized, web3.eth.sign) - const sig = await getParsedSignatureOfAddress(web3, releaseGoldInstance.address, authorized) - await releaseGoldInstance.authorizeValidatorSignerWithPublicKey( - authorized, - sig.v, - sig.r, - sig.s, - ecdsaPublicKey as any, - { from: beneficiary } - ) - }) - - it('should set the authorized keys', async () => { - assert.equal(await accountsInstance.authorizedBy(authorized), releaseGoldInstance.address) - assert.equal( - await accountsInstance.getValidatorSigner(releaseGoldInstance.address), - authorized - ) - assert.equal( - await accountsInstance.validatorSignerToAccount(authorized), - releaseGoldInstance.address - ) - }) - }) - - describe('with bls keys', () => { - beforeEach(async () => { - const releaseGoldSchedule = _.clone(releaseGoldDefaultSchedule) - releaseGoldSchedule.revocable = false - releaseGoldSchedule.canValidate = true - releaseGoldSchedule.refundAddress = NULL_ADDRESS - await createNewReleaseGoldInstance(releaseGoldSchedule, web3) - await releaseGoldInstance.createAccount({ from: beneficiary }) - const ecdsaPublicKey = await addressToPublicKey(authorized, web3.eth.sign) - const newBlsPublicKey = web3.utils.randomHex(96) - const newBlsPoP = web3.utils.randomHex(48) - - const sig = await getParsedSignatureOfAddress(web3, releaseGoldInstance.address, authorized) - await releaseGoldInstance.authorizeValidatorSignerWithKeys( - authorized, - sig.v, - sig.r, - sig.s, - ecdsaPublicKey as any, - newBlsPublicKey, - newBlsPoP, - { from: beneficiary } - ) - }) - - it('should set the authorized keys', async () => { - assert.equal(await accountsInstance.authorizedBy(authorized), releaseGoldInstance.address) - assert.equal( - await accountsInstance.getValidatorSigner(releaseGoldInstance.address), - authorized - ) - assert.equal( - await accountsInstance.validatorSignerToAccount(authorized), - releaseGoldInstance.address - ) - }) - }) - }) - - describe('#revoke', () => { - it('releaseOwner should be able to revoke the releaseGold', async () => { - await createNewReleaseGoldInstance(releaseGoldDefaultSchedule, web3) - const releaseOwnereleaseGoldTx = await releaseGoldInstance.revoke({ from: releaseOwner }) - const revokeBlockTimestamp = await getCurrentBlockchainTimestamp(web3) - const [, , , releaseGoldRevokeTime] = await releaseGoldInstance.revocationInfo() - assertEqualBN(revokeBlockTimestamp, releaseGoldRevokeTime) - assert.isTrue(await releaseGoldInstance.isRevoked()) - assertLogMatches(releaseOwnereleaseGoldTx.logs[0], 'ReleaseScheduleRevoked', { - revokeTimestamp: revokeBlockTimestamp, - releasedBalanceAtRevoke: await releaseGoldInstance.getCurrentReleasedTotalAmount(), - }) - }) - - it('should revert when non-releaseOwner attempts to revoke the releaseGold', async () => { - await createNewReleaseGoldInstance(releaseGoldDefaultSchedule, web3) - await assertTransactionRevertWithReason( - releaseGoldInstance.revoke({ from: accounts[5] }), - 'Sender must be the registered releaseOwner address' - ) - }) - - it('should revert if releaseGold is already revoked', async () => { - await createNewReleaseGoldInstance(releaseGoldDefaultSchedule, web3) - await releaseGoldInstance.revoke({ from: releaseOwner }) - await assertTransactionRevertWithReason( - releaseGoldInstance.revoke({ from: releaseOwner }), - 'Release schedule instance must not already be revoked' - ) - }) - - it('should revert if releaseGold is non-revocable', async () => { - const releaseGoldSchedule = _.clone(releaseGoldDefaultSchedule) - releaseGoldSchedule.revocable = false - releaseGoldSchedule.refundAddress = '0x0000000000000000000000000000000000000000' - await createNewReleaseGoldInstance(releaseGoldSchedule, web3) - await assertTransactionRevertWithReason( - releaseGoldInstance.revoke({ from: releaseOwner }), - 'Release schedule instance must be revocable' - ) - }) - }) - - describe('#expire', () => { - describe('when the contract is expirable', () => { - beforeEach(async () => { - await createNewReleaseGoldInstance(releaseGoldDefaultSchedule, web3) - }) - - describe('when called before expiration time has passed', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - releaseGoldInstance.expire({ from: releaseOwner }), - '`EXPIRATION_TIME` must have passed after the end of releasing' - ) - }) - }) - - describe('when the contract has finished releasing', () => { - beforeEach(async () => { - const [, , numReleasePeriods, releasePeriod] = await releaseGoldInstance.releaseSchedule() - const grantTime = numReleasePeriods - .times(releasePeriod) - .plus(5 * MINUTE) - .toNumber() - await timeTravel(grantTime, web3) - }) - - it('should revert before `EXPIRATION_TIME` after release schedule end', async () => { - await assertTransactionRevertWithReason( - releaseGoldInstance.expire({ from: releaseOwner }), - '`EXPIRATION_TIME` must have passed after the end of releasing' - ) - }) - - describe('when `EXPIRATION_TIME` has passed after release schedule completion', () => { - beforeEach(async () => { - const expirationTime = await releaseGoldInstance.EXPIRATION_TIME() - const timeToTravel = expirationTime.toNumber() - await timeTravel(timeToTravel, web3) - }) - describe('when not called by releaseOwner', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - releaseGoldInstance.expire(), - 'Sender must be the registered releaseOwner address' - ) - }) - }) - - describe('when called by releaseOwner', () => { - it('should succeed', async () => { - await releaseGoldInstance.expire({ from: releaseOwner }) - }) - }) - - describe('when an instance is expired', () => { - describe('when the beneficiary has not withdrawn any balance yet', () => { - beforeEach(async () => { - await releaseGoldInstance.expire({ from: releaseOwner }) - }) - - it('should revoke the contract', async () => { - const isRevoked = await releaseGoldInstance.isRevoked() - assert.equal(isRevoked, true) - }) - - it('should set the released balance at revocation to total withdrawn', async () => { - const [, , releasedBalanceAtRevoke] = await releaseGoldInstance.revocationInfo() - // 0 gold withdrawn at this point - assertEqualBN(releasedBalanceAtRevoke, 0) - }) - - it('should allow refund of all remaining gold', async () => { - const refundAddressBalanceBefore = await goldTokenInstance.balanceOf(refundAddress) - await releaseGoldInstance.refundAndFinalize({ from: releaseOwner }) - const refundAddressBalanceAfter = await goldTokenInstance.balanceOf(refundAddress) - assertEqualBN( - refundAddressBalanceAfter.minus(refundAddressBalanceBefore), - TOTAL_AMOUNT - ) - }) - }) - - describe('when the beneficiary has withdrawn some balance', () => { - beforeEach(async () => { - await releaseGoldInstance.withdraw(TOTAL_AMOUNT.div(2), { from: beneficiary }) - await releaseGoldInstance.expire({ from: releaseOwner }) - }) - - it('should revoke the contract', async () => { - const isRevoked = await releaseGoldInstance.isRevoked() - assert.equal(isRevoked, true) - }) - - it('should set the released balance at revocation to total withdrawn', async () => { - const [, , releasedBalanceAtRevoke] = await releaseGoldInstance.revocationInfo() - // half of gold withdrawn at this point - assertEqualBN(releasedBalanceAtRevoke, TOTAL_AMOUNT.div(2)) - }) - - it('should allow refund of all remaining gold', async () => { - const refundAddressBalanceBefore = await goldTokenInstance.balanceOf(refundAddress) - await releaseGoldInstance.refundAndFinalize({ from: releaseOwner }) - const refundAddressBalanceAfter = await goldTokenInstance.balanceOf(refundAddress) - assertEqualBN( - refundAddressBalanceAfter.minus(refundAddressBalanceBefore), - TOTAL_AMOUNT.div(2) - ) - }) - }) - }) - }) - }) - }) - - describe('when the contract is not expirable', () => { - beforeEach(async () => { - await createNewReleaseGoldInstance(releaseGoldDefaultSchedule, web3) - await releaseGoldInstance.setCanExpire(false, { from: beneficiary }) - const [, , numReleasePeriods, releasePeriod] = await releaseGoldInstance.releaseSchedule() - const expirationTime = await releaseGoldInstance.EXPIRATION_TIME() - const grantTime = numReleasePeriods.times(releasePeriod).plus(5 * MINUTE) - const timeToTravel = grantTime.plus(expirationTime).toNumber() - await timeTravel(timeToTravel, web3) - }) - - describe('when `expire` is called', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - releaseGoldInstance.expire({ from: releaseOwner }), - 'Contract must be expirable' - ) - }) - }) - }) - }) - - describe('#refundAndFinalize', () => { - beforeEach(async () => { - await createNewReleaseGoldInstance(releaseGoldDefaultSchedule, web3) - // wait some time for some gold to release - const timeToTravel = 7 * MONTH - await timeTravel(timeToTravel, web3) - }) - - it('should only be callable by releaseOwner and when revoked', async () => { - await releaseGoldInstance.revoke({ from: releaseOwner }) - await releaseGoldInstance.refundAndFinalize({ from: releaseOwner }) - }) - - it('should revert when revoked but called by a non-releaseOwner', async () => { - await releaseGoldInstance.revoke({ from: releaseOwner }) - await assertTransactionRevertWithReason( - releaseGoldInstance.refundAndFinalize({ from: accounts[5] }), - 'Sender must be the releaseOwner and state must be revoked' - ) - }) - - it('should revert when non-revoked but called by a releaseOwner', async () => { - await assertTransactionRevertWithReason( - releaseGoldInstance.refundAndFinalize({ from: releaseOwner }), - 'Sender must be the releaseOwner and state must be revoked' - ) - }) - - describe('when revoked()', () => { - beforeEach(async () => { - await releaseGoldInstance.revoke({ from: releaseOwner }) - }) - - it('should transfer gold proportions to both beneficiary and refundAddress when no gold locked', async () => { - const beneficiaryBalanceBefore = await goldTokenInstance.balanceOf(beneficiary) - const refundAddressBalanceBefore = await goldTokenInstance.balanceOf(refundAddress) - const [, , releasedBalanceAtRevoke] = await releaseGoldInstance.revocationInfo() - const beneficiaryRefundAmount = new BigNumber(releasedBalanceAtRevoke).minus( - await releaseGoldInstance.totalWithdrawn() - ) - const refundAddressRefundAmount = new BigNumber( - await goldTokenInstance.balanceOf(releaseGoldInstance.address) - ).minus(beneficiaryRefundAmount) - await releaseGoldInstance.refundAndFinalize({ from: releaseOwner }) - const contractBalanceAfterFinalize = await goldTokenInstance.balanceOf( - releaseGoldInstance.address - ) - const beneficiaryBalanceAfter = await goldTokenInstance.balanceOf(beneficiary) - const refundAddressBalanceAfter = await goldTokenInstance.balanceOf(refundAddress) - - assertEqualBN( - new BigNumber(beneficiaryBalanceAfter).minus(new BigNumber(beneficiaryBalanceBefore)), - beneficiaryRefundAmount - ) - assertEqualBN( - new BigNumber(refundAddressBalanceAfter).minus(new BigNumber(refundAddressBalanceBefore)), - refundAddressRefundAmount - ) - - assertEqualBN(contractBalanceAfterFinalize, 0) - }) - - it('should destruct releaseGold instance after finalizing and prevent calling further actions', async () => { - await releaseGoldInstance.refundAndFinalize({ from: releaseOwner }) - try { - await releaseGoldInstance.getRemainingUnlockedBalance() - } catch (ex) { - return assert.isTrue(true) - } - - return assert.isTrue(false) - }) - }) - }) - - describe('#lockGold', () => { - let lockAmount = null - - beforeEach(async () => { - await createNewReleaseGoldInstance(releaseGoldDefaultSchedule, web3) - lockAmount = releaseGoldDefaultSchedule.amountReleasedPerPeriod.multipliedBy( - releaseGoldDefaultSchedule.numReleasePeriods - ) - }) - - it('beneficiary should lock up any unlocked amount', async () => { - // beneficiary shall make the released gold instance an account - await releaseGoldInstance.createAccount({ from: beneficiary }) - await releaseGoldInstance.lockGold(lockAmount, { - from: beneficiary, - }) - assertEqualBN( - await lockedGoldInstance.getAccountTotalLockedGold(releaseGoldInstance.address), - lockAmount - ) - assertEqualBN( - await lockedGoldInstance.getAccountNonvotingLockedGold(releaseGoldInstance.address), - lockAmount - ) - assertEqualBN(await lockedGoldInstance.getNonvotingLockedGold(), lockAmount) - assertEqualBN(await lockedGoldInstance.getTotalLockedGold(), lockAmount) - }) - - it('should revert if releaseGold instance is not an account', async () => { - await assertTransactionRevertWithReason( - releaseGoldInstance.lockGold(lockAmount, { - from: beneficiary, - }), - 'Must first register address with Account.createAccount' - ) - }) - - it('should revert if beneficiary tries to lock up more than there is remaining in the contract', async () => { - await releaseGoldInstance.createAccount({ from: beneficiary }) - await assertTransactionRevertWithoutReason( - releaseGoldInstance.lockGold(lockAmount.multipliedBy(1.1), { - from: beneficiary, - }) - ) - }) - - it('should revert if non-beneficiary tries to lock up any unlocked amount', async () => { - await releaseGoldInstance.createAccount({ from: beneficiary }) - await assertTransactionRevertWithReason( - releaseGoldInstance.lockGold(lockAmount, { from: accounts[6] }), - 'Sender must be the beneficiary and state must not be revoked' - ) - }) - }) - - describe('#unlockGold', () => { - let lockAmount: any - - beforeEach(async () => { - await createNewReleaseGoldInstance(releaseGoldDefaultSchedule, web3) - // beneficiary shall make the released gold instance an account - await releaseGoldInstance.createAccount({ from: beneficiary }) - lockAmount = releaseGoldDefaultSchedule.amountReleasedPerPeriod.multipliedBy( - releaseGoldDefaultSchedule.numReleasePeriods - ) - }) - - it('beneficiary should unlock his locked gold and add a pending withdrawal', async () => { - await releaseGoldInstance.lockGold(lockAmount, { - from: beneficiary, - }) - await releaseGoldInstance.unlockGold(lockAmount, { - from: beneficiary, - }) - - const [values, timestamps] = await lockedGoldInstance.getPendingWithdrawals( - releaseGoldInstance.address - ) - assert.equal(values.length, 1) - assert.equal(timestamps.length, 1) - assertEqualBN(values[0], lockAmount) - assertEqualBN(timestamps[0], (await getCurrentBlockchainTimestamp(web3)) + UNLOCKING_PERIOD) - - assertEqualBN( - await lockedGoldInstance.getAccountTotalLockedGold(releaseGoldInstance.address), - 0 - ) - // ReleaseGold locked balance should still reflect pending withdrawals - assertEqualBN(await releaseGoldInstance.getRemainingLockedBalance(), lockAmount) - assertEqualBN( - await lockedGoldInstance.getAccountNonvotingLockedGold(releaseGoldInstance.address), - 0 - ) - assertEqualBN(await lockedGoldInstance.getNonvotingLockedGold(), 0) - assertEqualBN(await lockedGoldInstance.getTotalLockedGold(), 0) - }) - - it('should revert if non-beneficiary tries to unlock the locked amount', async () => { - // lock the entire releaseGold amount - await releaseGoldInstance.lockGold(lockAmount, { - from: beneficiary, - }) - // unlock the latter - await assertTransactionRevertWithReason( - releaseGoldInstance.unlockGold(lockAmount, { from: accounts[5] }), - 'Must be called by releaseOwner when revoked or beneficiary before revocation' - ) - }) - - it('should revert if beneficiary in voting tries to unlock the locked amount', async () => { - // set the contract in voting - await mockGovernance.setVoting(releaseGoldInstance.address) - // lock the entire releaseGold amount - await releaseGoldInstance.lockGold(lockAmount, { - from: beneficiary, - }) - // unlock the latter - await assertTransactionRevertWithReason( - releaseGoldInstance.unlockGold(lockAmount, { from: accounts[5] }), - 'Must be called by releaseOwner when revoked or beneficiary before revocation' - ) - }) - - it('should revert if beneficiary with balance requirements tries to unlock the locked amount', async () => { - // set the contract in voting - await mockGovernance.setVoting(releaseGoldInstance.address) - // lock the entire releaseGold amount - await releaseGoldInstance.lockGold(lockAmount, { - from: beneficiary, - }) - // set some balance requirements - const balanceRequirement = 10 - await mockValidators.setAccountLockedGoldRequirement( - releaseGoldInstance.address, - balanceRequirement - ) - // unlock the latter - await assertTransactionRevertWithReason( - releaseGoldInstance.unlockGold(lockAmount, { from: beneficiary }), - "Either account doesn't have enough locked Celo or locked Celo is being used for voting." - ) - }) - }) - - describe('#withdrawLockedGold', () => { - const value = 1000 - const index = 0 - - describe('when a pending withdrawal exists', () => { - beforeEach(async () => { - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - await createNewReleaseGoldInstance(releaseGoldDefaultSchedule, web3) - await releaseGoldInstance.createAccount({ from: beneficiary }) - await releaseGoldInstance.lockGold(value, { from: beneficiary }) - await releaseGoldInstance.unlockGold(value, { from: beneficiary }) - }) - - describe('when it is after the availablity time', () => { - beforeEach(async () => { - await timeTravel(UNLOCKING_PERIOD, web3) - await releaseGoldInstance.withdrawLockedGold(index, { from: beneficiary }) - }) - - it('should remove the pending withdrawal', async () => { - const [values, timestamps] = await lockedGoldInstance.getPendingWithdrawals( - releaseGoldInstance.address - ) - assert.equal(values.length, 0) - assert.equal(timestamps.length, 0) - assertEqualBN(await releaseGoldInstance.getRemainingLockedBalance(), 0) - }) - }) - - describe('when it is before the availablity time', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - releaseGoldInstance.withdrawLockedGold(index, { from: beneficiary }), - 'Pending withdrawal not available' - ) - }) - }) - - describe('when non-beneficiary attempts to withdraw the gold', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - releaseGoldInstance.withdrawLockedGold(index, { from: accounts[4] }), - 'Must be called by releaseOwner when revoked or beneficiary before revocation' - ) - }) - }) - }) - - describe('when a pending withdrawal does not exist', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - releaseGoldInstance.withdrawLockedGold(index, { from: beneficiary }), - 'Pending withdrawal not available' - ) - }) - }) - }) - - describe('#relockGold', () => { - const pendingWithdrawalValue = 1000 - const index = 0 - - beforeEach(async () => { - // @ts-ignore: TODO(mcortesi) fix typings for TransactionDetails - await createNewReleaseGoldInstance(releaseGoldDefaultSchedule, web3) - await releaseGoldInstance.createAccount({ from: beneficiary }) - await releaseGoldInstance.lockGold(pendingWithdrawalValue, { from: beneficiary }) - await releaseGoldInstance.unlockGold(pendingWithdrawalValue, { from: beneficiary }) - }) - - describe('when a pending withdrawal exists', () => { - describe('when relocking value equal to the value of the pending withdrawal', () => { - const value = pendingWithdrawalValue - beforeEach(async () => { - await releaseGoldInstance.relockGold(index, value, { from: beneficiary }) - }) - - it("should increase the account's nonvoting locked gold balance", async () => { - assertEqualBN( - await lockedGoldInstance.getAccountNonvotingLockedGold(releaseGoldInstance.address), - value - ) - }) - - it("should increase the account's total locked gold balance", async () => { - assertEqualBN( - await lockedGoldInstance.getAccountTotalLockedGold(releaseGoldInstance.address), - value - ) - }) - - it('should increase the nonvoting locked gold balance', async () => { - assertEqualBN(await lockedGoldInstance.getNonvotingLockedGold(), value) - }) - - it('should increase the total locked gold balance', async () => { - assertEqualBN(await lockedGoldInstance.getTotalLockedGold(), value) - }) - - it('should remove the pending withdrawal', async () => { - const [values, timestamps] = await lockedGoldInstance.getPendingWithdrawals( - releaseGoldInstance.address - ) - assert.equal(values.length, 0) - assert.equal(timestamps.length, 0) - }) - }) - - describe('when relocking value less than the value of the pending withdrawal', () => { - const value = pendingWithdrawalValue - 1 - beforeEach(async () => { - await releaseGoldInstance.relockGold(index, value, { from: beneficiary }) - }) - - it("should increase the account's nonvoting locked gold balance", async () => { - assertEqualBN( - await lockedGoldInstance.getAccountNonvotingLockedGold(releaseGoldInstance.address), - value - ) - }) - - it("should increase the account's total locked gold balance", async () => { - assertEqualBN( - await lockedGoldInstance.getAccountTotalLockedGold(releaseGoldInstance.address), - value - ) - }) - - it('should increase the nonvoting locked gold balance', async () => { - assertEqualBN(await lockedGoldInstance.getNonvotingLockedGold(), value) - }) - - it('should increase the total locked gold balance', async () => { - assertEqualBN(await lockedGoldInstance.getTotalLockedGold(), value) - }) - - it('should decrement the value of the pending withdrawal', async () => { - const [values, timestamps] = await lockedGoldInstance.getPendingWithdrawals( - releaseGoldInstance.address - ) - assert.equal(values.length, 1) - assert.equal(timestamps.length, 1) - assertEqualBN(values[0], 1) - }) - }) - - describe('when relocking value greater than the value of the pending withdrawal', () => { - const value = pendingWithdrawalValue + 1 - it('should revert', async () => { - await assertTransactionRevertWithReason( - releaseGoldInstance.relockGold(index, value, { from: beneficiary }), - 'Requested value larger than pending value' - ) - }) - }) - }) - - describe('when a pending withdrawal does not exist', () => { - it('should revert', async () => { - await assertTransactionRevertWithReason( - releaseGoldInstance.relockGold(index, pendingWithdrawalValue), - 'Sender must be the beneficiary and state must not be revoked' - ) - }) - }) - }) - - describe('#withdraw', () => { - let initialreleaseGoldAmount: any - - beforeEach(async () => { - const releaseGoldSchedule = _.clone(releaseGoldDefaultSchedule) - releaseGoldSchedule.releaseStartTime = Math.round(Date.now() / 1000) - releaseGoldSchedule.initialDistributionRatio = 0 - await createNewReleaseGoldInstance(releaseGoldSchedule, web3) - initialreleaseGoldAmount = releaseGoldSchedule.amountReleasedPerPeriod.multipliedBy( - releaseGoldSchedule.numReleasePeriods - ) - }) - - it('should revert before the release cliff has passed', async () => { - await releaseGoldInstance.setMaxDistribution(1000, { from: releaseOwner }) - const timeToTravel = 0.5 * HOUR - await timeTravel(timeToTravel, web3) - await assertTransactionRevertWithReason( - releaseGoldInstance.withdraw(initialreleaseGoldAmount.div(20), { from: beneficiary }), - 'Requested amount is greater than available released funds' - ) - }) - - it('should revert when withdrawable amount is zero', async () => { - await releaseGoldInstance.setMaxDistribution(1000, { from: releaseOwner }) - const timeToTravel = 3 * MONTH + 1 * DAY - await timeTravel(timeToTravel, web3) - await assertTransactionRevertWithReason( - releaseGoldInstance.withdraw(new BigNumber(0), { from: beneficiary }), - 'Requested withdrawal amount must be greater than zero' - ) - }) - - describe('when not revoked', () => { - describe('when max distribution is 100%', () => { - beforeEach(async () => { - await releaseGoldInstance.setMaxDistribution(1000, { from: releaseOwner }) - }) - it('should revert since beneficiary should not be able to withdraw anything within the first quarter', async () => { - const beneficiaryBalanceBefore = await goldTokenInstance.balanceOf(beneficiary) - const timeToTravel = 2.9 * MONTH - await timeTravel(timeToTravel, web3) - const expectedWithdrawalAmount = await releaseGoldInstance.getCurrentReleasedTotalAmount() - const beneficiaryBalanceAfter = await goldTokenInstance.balanceOf(beneficiary) - assertEqualBN(expectedWithdrawalAmount, 0) - await assertTransactionRevertWithReason( - releaseGoldInstance.withdraw(expectedWithdrawalAmount, { from: beneficiary }), - 'Requested withdrawal amount must be greater than zero' - ) - assertEqualBN( - new BigNumber(beneficiaryBalanceAfter).minus(new BigNumber(beneficiaryBalanceBefore)), - 0 - ) - }) - - it('should allow the beneficiary to withdraw 25% of the released amount of gold right after the beginning of the first quarter', async () => { - const beneficiaryBalanceBefore = await goldTokenInstance.balanceOf(beneficiary) - const timeToTravel = 3 * MONTH + 1 * DAY - await timeTravel(timeToTravel, web3) - const expectedWithdrawalAmount = initialreleaseGoldAmount.div(4) - await releaseGoldInstance.withdraw(expectedWithdrawalAmount, { from: beneficiary }) - const totalWithdrawn = await releaseGoldInstance.totalWithdrawn() - const beneficiaryBalanceAfter = await goldTokenInstance.balanceOf(beneficiary) - expectBigNumberInRange(new BigNumber(totalWithdrawn), expectedWithdrawalAmount) - expectBigNumberInRange( - new BigNumber(beneficiaryBalanceAfter).minus(new BigNumber(beneficiaryBalanceBefore)), - expectedWithdrawalAmount - ) - }) - - it('should allow the beneficiary to withdraw 50% the released amount of gold when half of the release periods have passed', async () => { - const beneficiaryBalanceBefore = await goldTokenInstance.balanceOf(beneficiary) - const timeToTravel = 6 * MONTH + 1 * DAY - await timeTravel(timeToTravel, web3) - const expectedWithdrawalAmount = initialreleaseGoldAmount.div(2) - await releaseGoldInstance.withdraw(expectedWithdrawalAmount, { from: beneficiary }) - const totalWithdrawn = await releaseGoldInstance.totalWithdrawn() - const beneficiaryBalanceAfter = await goldTokenInstance.balanceOf(beneficiary) - assertEqualBN(new BigNumber(totalWithdrawn), expectedWithdrawalAmount) - expectBigNumberInRange( - new BigNumber(beneficiaryBalanceAfter).minus(new BigNumber(beneficiaryBalanceBefore)), - expectedWithdrawalAmount - ) - }) - - it('should allow the beneficiary to withdraw 75% of the released amount of gold right after the beginning of the third quarter', async () => { - const beneficiaryBalanceBefore = await goldTokenInstance.balanceOf(beneficiary) - const timeToTravel = 9 * MONTH + 1 * DAY - await timeTravel(timeToTravel, web3) - const expectedWithdrawalAmount = initialreleaseGoldAmount.multipliedBy(3).div(4) - await releaseGoldInstance.withdraw(expectedWithdrawalAmount, { from: beneficiary }) - const beneficiaryBalanceAfter = await goldTokenInstance.balanceOf(beneficiary) - const totalWithdrawn = await releaseGoldInstance.totalWithdrawn() - assertEqualBN(new BigNumber(totalWithdrawn), expectedWithdrawalAmount) - expectBigNumberInRange( - new BigNumber(beneficiaryBalanceAfter).minus(new BigNumber(beneficiaryBalanceBefore)), - expectedWithdrawalAmount - ) - }) - - it('should allow the beneficiary to withdraw 100% of the amount right after the end of the release period', async () => { - const beneficiaryBalanceBefore = await goldTokenInstance.balanceOf(beneficiary) - const timeToTravel = 12 * MONTH + 1 * DAY - await timeTravel(timeToTravel, web3) - const expectedWithdrawalAmount = initialreleaseGoldAmount - await releaseGoldInstance.withdraw(expectedWithdrawalAmount, { from: beneficiary }) - const beneficiaryBalanceAfter = await goldTokenInstance.balanceOf(beneficiary) - - expectBigNumberInRange( - new BigNumber(beneficiaryBalanceAfter).minus(new BigNumber(beneficiaryBalanceBefore)), - expectedWithdrawalAmount - ) - }) - - it('should destruct releaseGold instance when the entire balance is withdrawn', async () => { - const timeToTravel = 12 * MONTH + 1 * DAY - await timeTravel(timeToTravel, web3) - const expectedWithdrawalAmount = initialreleaseGoldAmount - await releaseGoldInstance.withdraw(expectedWithdrawalAmount, { from: beneficiary }) - - try { - await releaseGoldInstance.totalWithdrawn() - return assert.isTrue(false) - } catch (ex) { - return assert.isTrue(true) - } - }) - - describe('when rewards are simulated', () => { - beforeEach(async () => { - // Simulate rewards of 0.5 Gold - await goldTokenInstance.transfer(releaseGoldInstance.address, ONE_GOLDTOKEN.div(2), { - from: owner, - }) - // Default distribution is 100% - }) - - describe('when the grant has fully released', () => { - beforeEach(async () => { - const timeToTravel = 12 * MONTH + 1 * DAY - await timeTravel(timeToTravel, web3) - }) - - it('should allow distribution of initial balance and rewards', async () => { - const expectedWithdrawalAmount = TOTAL_AMOUNT.plus(ONE_GOLDTOKEN.div(2)) - await releaseGoldInstance.withdraw(expectedWithdrawalAmount, { from: beneficiary }) - }) - }) - - describe('when the grant is only halfway released', () => { - beforeEach(async () => { - const timeToTravel = 6 * MONTH + 1 * DAY - await timeTravel(timeToTravel, web3) - }) - - it('should scale released amount to 50% of initial balance plus rewards', async () => { - const expectedWithdrawalAmount = TOTAL_AMOUNT.plus(ONE_GOLDTOKEN.div(2)).div(2) - await releaseGoldInstance.withdraw(expectedWithdrawalAmount, { from: beneficiary }) - }) - - it('should not allow withdrawal of more than 50% gold', async () => { - const unexpectedWithdrawalAmount = TOTAL_AMOUNT.plus(ONE_GOLDTOKEN).div(2).plus(1) - await assertTransactionRevertWithReason( - releaseGoldInstance.withdraw(unexpectedWithdrawalAmount, { from: beneficiary }), - 'Requested amount is greater than available released funds' - ) - }) - }) - }) - }) - - // Max distribution should set a static value of `ratio` of total funds at call time of `setMaxDistribution` - // So this is testing that the maxDistribution is unrelated to rewards, except the 100% special case. - describe('when max distribution is 50% and all gold is released', () => { - beforeEach(async () => { - await releaseGoldInstance.setMaxDistribution(500, { from: releaseOwner }) - // Simulate rewards of 0.5 Gold - // Have to send after setting max distribution as mentioned above - await goldTokenInstance.transfer(releaseGoldInstance.address, ONE_GOLDTOKEN.div(2), { - from: owner, - }) - const timeToTravel = 12 * MONTH + 1 * DAY - await timeTravel(timeToTravel, web3) - }) - - it('should only allow withdrawal of 50% of initial grant (not including rewards)', async () => { - const expectedWithdrawalAmount = TOTAL_AMOUNT.div(2) - await releaseGoldInstance.withdraw(expectedWithdrawalAmount, { from: beneficiary }) - const unexpectedWithdrawalAmount = 1 - await assertTransactionRevertWithReason( - releaseGoldInstance.withdraw(unexpectedWithdrawalAmount, { from: beneficiary }), - 'Requested amount exceeds current alloted maximum distribution' - ) - }) - }) - }) - - describe('when revoked', () => { - describe('when max distribution is 100%', () => { - beforeEach(async () => { - await releaseGoldInstance.setMaxDistribution(1000, { from: releaseOwner }) - }) - it('should allow the beneficiary to withdraw up to the releasedBalanceAtRevoke', async () => { - const beneficiaryBalanceBefore = await goldTokenInstance.balanceOf(beneficiary) - const timeToTravel = 6 * MONTH + 1 * DAY - await timeTravel(timeToTravel, web3) - await releaseGoldInstance.revoke({ from: releaseOwner }) - const [, , expectedWithdrawalAmount] = await releaseGoldInstance.revocationInfo() - await releaseGoldInstance.withdraw(expectedWithdrawalAmount, { from: beneficiary }) - const totalWithdrawn = await releaseGoldInstance.totalWithdrawn() - const beneficiaryBalanceAfter = await goldTokenInstance.balanceOf(beneficiary) - expectBigNumberInRange(new BigNumber(totalWithdrawn), expectedWithdrawalAmount) - expectBigNumberInRange( - new BigNumber(beneficiaryBalanceAfter).minus(new BigNumber(beneficiaryBalanceBefore)), - expectedWithdrawalAmount - ) - }) - - it('should revert if beneficiary attempts to withdraw more than releasedBalanceAtRevoke', async () => { - const timeToTravel = 6 * MONTH + 1 * DAY - await timeTravel(timeToTravel, web3) - await releaseGoldInstance.revoke({ from: releaseOwner }) - const [, , expectedWithdrawalAmount] = await releaseGoldInstance.revocationInfo() - await assertTransactionRevertWithReason( - releaseGoldInstance.withdraw( - new BigNumber(expectedWithdrawalAmount).multipliedBy(1.1), - { - from: beneficiary, - } - ), - 'Requested amount is greater than available released funds' - ) - }) - - it('should selfdestruct if beneficiary withdraws the entire amount', async () => { - const beneficiaryBalanceBefore = await goldTokenInstance.balanceOf(beneficiary) - const timeToTravel = 12 * MONTH + 1 * DAY - await timeTravel(timeToTravel, web3) - await releaseGoldInstance.revoke({ from: releaseOwner }) - const [, , expectedWithdrawalAmount] = await releaseGoldInstance.revocationInfo() - await releaseGoldInstance.withdraw(expectedWithdrawalAmount, { from: beneficiary }) - const beneficiaryBalanceAfter = await goldTokenInstance.balanceOf(beneficiary) - - expectBigNumberInRange( - new BigNumber(beneficiaryBalanceAfter).minus(new BigNumber(beneficiaryBalanceBefore)), - expectedWithdrawalAmount - ) - - try { - await releaseGoldInstance.totalWithdrawn() - return assert.isTrue(false) - } catch (ex) { - return assert.isTrue(true) - } - }) - }) - }) - - describe('when max distribution is set lower', () => { - let beneficiaryBalanceBefore: any - beforeEach(async () => { - beneficiaryBalanceBefore = await goldTokenInstance.balanceOf(beneficiary) - const timeToTravel = 12 * MONTH + 1 * DAY - await timeTravel(timeToTravel, web3) - }) - - describe('when max distribution is 50%', () => { - beforeEach(async () => { - await releaseGoldInstance.setMaxDistribution(500, { from: releaseOwner }) - }) - - it('should allow withdrawal of 50%', async () => { - const expectedWithdrawalAmount = initialreleaseGoldAmount.multipliedBy(0.5) - await releaseGoldInstance.withdraw(expectedWithdrawalAmount, { from: beneficiary }) - const beneficiaryBalanceAfter = await goldTokenInstance.balanceOf(beneficiary) - - expectBigNumberInRange( - new BigNumber(beneficiaryBalanceAfter).minus(new BigNumber(beneficiaryBalanceBefore)), - expectedWithdrawalAmount - ) - }) - - it('should revert on withdrawal of more than 50%', async () => { - await assertTransactionRevertWithReason( - releaseGoldInstance.withdraw(initialreleaseGoldAmount, { from: beneficiary }), - 'Requested amount exceeds current alloted maximum distribution' - ) - }) - }) - - describe('when max distribution is 100%', () => { - beforeEach(async () => { - await releaseGoldInstance.setMaxDistribution(1000, { from: releaseOwner }) - }) - - it('should allow withdrawal of all gold', async () => { - const expectedWithdrawalAmount = initialreleaseGoldAmount - await releaseGoldInstance.withdraw(expectedWithdrawalAmount, { from: beneficiary }) - const beneficiaryBalanceAfter = await goldTokenInstance.balanceOf(beneficiary) - - expectBigNumberInRange( - new BigNumber(beneficiaryBalanceAfter).minus(new BigNumber(beneficiaryBalanceBefore)), - expectedWithdrawalAmount - ) - }) - }) - }) - - describe('when the liquidity provision is observed and set false', () => { - beforeEach(async () => { - const releaseGoldSchedule = _.clone(releaseGoldDefaultSchedule) - releaseGoldSchedule.subjectToLiquidityProvision = true - await createNewReleaseGoldInstance(releaseGoldSchedule, web3) - // Withdraw `beforeEach` creates one instance, have to grab the second - const timeToTravel = 12 * MONTH + 1 * DAY - await timeTravel(timeToTravel, web3) - }) - - it('should revert on withdraw of any amount', async () => { - await assertTransactionRevertWithReason( - releaseGoldInstance.withdraw(initialreleaseGoldAmount.multipliedBy(0.5), { - from: beneficiary, - }), - 'Requested withdrawal before liquidity provision is met' - ) - await assertTransactionRevertWithReason( - releaseGoldInstance.withdraw(initialreleaseGoldAmount, { from: beneficiary }), - 'Requested withdrawal before liquidity provision is met' - ) - }) - }) - }) - - describe('#getCurrentReleasedTotalAmount', () => { - let initialreleaseGoldAmount: any - - beforeEach(async () => { - const releaseGoldSchedule = _.clone(releaseGoldDefaultSchedule) - releaseGoldSchedule.releaseStartTime = Math.round(Date.now() / 1000) - await createNewReleaseGoldInstance(releaseGoldSchedule, web3) - initialreleaseGoldAmount = releaseGoldSchedule.amountReleasedPerPeriod.multipliedBy( - releaseGoldSchedule.numReleasePeriods - ) - }) - - it('should return zero if before cliff start time', async () => { - const timeToTravel = 0.5 * HOUR - await timeTravel(timeToTravel, web3) - const expectedWithdrawalAmount = 0 - assertEqualBN( - await releaseGoldInstance.getCurrentReleasedTotalAmount(), - expectedWithdrawalAmount - ) - }) - - it('should return 25% of the released amount of gold right after the beginning of the first quarter', async () => { - const timeToTravel = 3 * MONTH + 1 * DAY - await timeTravel(timeToTravel, web3) - const expectedWithdrawalAmount = initialreleaseGoldAmount.div(4) - assertEqualBN( - await releaseGoldInstance.getCurrentReleasedTotalAmount(), - expectedWithdrawalAmount - ) - }) - - it('should return 50% the released amount of gold right after the beginning of the second quarter', async () => { - const timeToTravel = 6 * MONTH + 1 * DAY - await timeTravel(timeToTravel, web3) - const expectedWithdrawalAmount = initialreleaseGoldAmount.div(2) - assertEqualBN( - await releaseGoldInstance.getCurrentReleasedTotalAmount(), - expectedWithdrawalAmount - ) - }) - - it('should return 75% of the released amount of gold right after the beginning of the third quarter', async () => { - const timeToTravel = 9 * MONTH + 1 * DAY - await timeTravel(timeToTravel, web3) - const expectedWithdrawalAmount = initialreleaseGoldAmount.multipliedBy(3).div(4) - assertEqualBN( - await releaseGoldInstance.getCurrentReleasedTotalAmount(), - expectedWithdrawalAmount - ) - }) - - it('should return 100% of the amount right after the end of the releaseGold period', async () => { - const timeToTravel = 12 * MONTH + 1 * DAY - await timeTravel(timeToTravel, web3) - const expectedWithdrawalAmount = initialreleaseGoldAmount - assertEqualBN( - await releaseGoldInstance.getCurrentReleasedTotalAmount(), - expectedWithdrawalAmount - ) - }) - }) - - describe('#getWithdrawableAmount', () => { - let initialReleaseGoldAmount: any - - beforeEach(async () => { - const releaseGoldSchedule = _.clone(releaseGoldDefaultSchedule) - releaseGoldSchedule.canValidate = true - releaseGoldSchedule.revocable = false - releaseGoldSchedule.refundAddress = '0x0000000000000000000000000000000000000000' - releaseGoldSchedule.releaseStartTime = Math.round(Date.now() / 1000) - releaseGoldSchedule.initialDistributionRatio = 500 - await createNewReleaseGoldInstance(releaseGoldSchedule, web3) - initialReleaseGoldAmount = releaseGoldSchedule.amountReleasedPerPeriod.multipliedBy( - releaseGoldSchedule.numReleasePeriods - ) - - await releaseGoldInstance.createAccount({ from: beneficiary }) - }) - - describe('should return 50% of the released amount of gold right after the beginning of the second quarter', async () => { - beforeEach(async () => { - await releaseGoldInstance.setMaxDistribution(1000, { from: releaseOwner }) - - const timeToTravel = 6 * MONTH + 1 * DAY - await timeTravel(timeToTravel, web3) - }) - - it('should return the full amount available for this release period', async () => { - const expectedWithdrawalAmount = initialReleaseGoldAmount.div(2) - const withdrawableAmount = await releaseGoldInstance.getWithdrawableAmount() - assertEqualBN(withdrawableAmount, expectedWithdrawalAmount) - }) - - it('should return only amount not yet withdrawn', async () => { - const expectedWithdrawalAmount = initialReleaseGoldAmount.div(2) - await releaseGoldInstance.withdraw(expectedWithdrawalAmount.div(2), { from: beneficiary }) - - const afterWithdrawal = await releaseGoldInstance.getWithdrawableAmount() - await releaseGoldInstance.getWithdrawableAmount() - assertEqualBN(afterWithdrawal, expectedWithdrawalAmount.div(2)) - }) - }) - - it('should return only up to its own balance', async () => { - await releaseGoldInstance.setMaxDistribution(1000, { from: releaseOwner }) - const timeToTravel = 6 * MONTH + 1 * DAY - await timeTravel(timeToTravel, web3) - const signerFund = new BigNumber('1000000000000000000') - const expectedWithdrawalAmount = initialReleaseGoldAmount.minus(signerFund).div(2) - - const authorized = accounts[4] - const ecdsaPublicKey = await addressToPublicKey(authorized, web3.eth.sign) - const sig = await getParsedSignatureOfAddress(web3, releaseGoldInstance.address, authorized) - // this will send 1 CELO from release gold balance to authorized - await releaseGoldInstance.authorizeValidatorSignerWithPublicKey( - authorized, - sig.v, - sig.r, - sig.s, - ecdsaPublicKey as any, - { from: beneficiary } - ) - - const withdrawableAmount = await releaseGoldInstance.getWithdrawableAmount() - assertEqualBN(withdrawableAmount, expectedWithdrawalAmount) - }) - - it('should return only up to max distribution', async () => { - const timeToTravel = 6 * MONTH + 1 * DAY - await timeTravel(timeToTravel, web3) - const expectedWithdrawalAmount = initialReleaseGoldAmount.div(2) - - await releaseGoldInstance.setMaxDistribution(250, { from: releaseOwner }) - - const withdrawableAmount = await releaseGoldInstance.getWithdrawableAmount() - assertEqualBN(withdrawableAmount, expectedWithdrawalAmount.div(2)) - }) - }) -}) diff --git a/packages/protocol/test/resources/compatibility/.gitignore b/packages/protocol/test/resources/compatibility/.gitignore deleted file mode 100644 index 1e012e204..000000000 --- a/packages/protocol/test/resources/compatibility/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# Don't commit the compiled test contracts -build/* diff --git a/packages/protocol/test/resources/compatibility/contracts_added_methods_and_contracts/Migrations.sol b/packages/protocol/test/resources/compatibility/contracts_added_methods_and_contracts/Migrations.sol deleted file mode 100644 index d1008cca7..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_added_methods_and_contracts/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.13; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_added_methods_and_contracts/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_added_methods_and_contracts/TestContract.sol deleted file mode 100644 index 12906811c..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_added_methods_and_contracts/TestContract.sol +++ /dev/null @@ -1,22 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - uint256 public x; - address public z; - - Thing public thing; - - function newMethod1(uint256 u) external {} - - function newMethod2(uint256 s) external pure returns (uint256) { - return s + 1; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_added_methods_and_contracts/TestContractNew.sol b/packages/protocol/test/resources/compatibility/contracts_added_methods_and_contracts/TestContractNew.sol deleted file mode 100644 index 74921c99e..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_added_methods_and_contracts/TestContractNew.sol +++ /dev/null @@ -1,16 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContractNew is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - uint256 public x; - address public z; - - Thing public thing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_added_methods_and_contracts/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_added_methods_and_contracts/TestLibrary.sol deleted file mode 100644 index 419c91139..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_added_methods_and_contracts/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_added_methods_and_contracts/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_added_methods_and_contracts/TestParent.sol deleted file mode 100644 index 502ef0a9f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_added_methods_and_contracts/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - TestLibrary.Thing libraryThing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_appended/Migrations.sol b/packages/protocol/test/resources/compatibility/contracts_appended/Migrations.sol deleted file mode 100644 index d1008cca7..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_appended/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.13; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_appended/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_appended/TestContract.sol deleted file mode 100644 index 33a6d7086..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_appended/TestContract.sol +++ /dev/null @@ -1,18 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - uint256 public x; - address public z; - - Thing public thing; - - uint256 public appendedVariable; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_appended/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_appended/TestLibrary.sol deleted file mode 100644 index 419c91139..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_appended/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_appended/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_appended/TestParent.sol deleted file mode 100644 index 502ef0a9f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_appended/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - TestLibrary.Thing libraryThing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_appended_in_parent/Migrations.sol b/packages/protocol/test/resources/compatibility/contracts_appended_in_parent/Migrations.sol deleted file mode 100644 index d1008cca7..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_appended_in_parent/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.13; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_appended_in_parent/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_appended_in_parent/TestContract.sol deleted file mode 100644 index e20424e4d..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_appended_in_parent/TestContract.sol +++ /dev/null @@ -1,16 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - uint256 public x; - address public z; - - Thing public thing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_appended_in_parent/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_appended_in_parent/TestLibrary.sol deleted file mode 100644 index 419c91139..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_appended_in_parent/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_appended_in_parent/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_appended_in_parent/TestParent.sol deleted file mode 100644 index d6bf20e25..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_appended_in_parent/TestParent.sol +++ /dev/null @@ -1,16 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - TestLibrary.Thing libraryThing; - - bool public appendedInParent; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_big_original/ImplementationChangeContract.sol b/packages/protocol/test/resources/compatibility/contracts_big_original/ImplementationChangeContract.sol deleted file mode 100644 index 4aba5f98d..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_big_original/ImplementationChangeContract.sol +++ /dev/null @@ -1,13 +0,0 @@ -pragma solidity ^0.5.13; - -contract ImplementationChangeContract { - uint256 i = 3; - - function someMethod1(uint256 u) external { - i = u; - } - - function someMethod2(uint256 s) external pure returns (uint256) { - return s + 1; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_big_original/MethodsAddedContract.sol b/packages/protocol/test/resources/compatibility/contracts_big_original/MethodsAddedContract.sol deleted file mode 100644 index 11f961d3c..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_big_original/MethodsAddedContract.sol +++ /dev/null @@ -1,13 +0,0 @@ -pragma solidity ^0.5.13; - -contract MethodsAddedContract { - uint256 i = 3; - - function someMethod1(uint256 u) external { - i = u; - } - - function someMethod2(uint256 s) external pure returns (uint256) { - return s + 1; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_big_original/MethodsModifiedContract.sol b/packages/protocol/test/resources/compatibility/contracts_big_original/MethodsModifiedContract.sol deleted file mode 100644 index c424dbf62..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_big_original/MethodsModifiedContract.sol +++ /dev/null @@ -1,25 +0,0 @@ -pragma solidity ^0.5.13; - -contract MethodsModifiedContract { - string a = "value"; - uint256 i = 3; - - function someMethod1(uint256 u) external { - i = u; - } - - function someMethod2(uint256 s) external pure returns (uint256) { - return s + 1; - } - - function someMethod3(uint256 s, string memory arg) public returns (uint256, string memory) { - string memory res = string(abi.encodePacked(arg, a)); - a = arg; - return (s + 1, res); - } - - function someMethod4(uint256 s) public payable returns (uint256) { - return s + 1; - } - -} diff --git a/packages/protocol/test/resources/compatibility/contracts_big_original/MethodsRemovedContract.sol b/packages/protocol/test/resources/compatibility/contracts_big_original/MethodsRemovedContract.sol deleted file mode 100644 index b31ba0b69..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_big_original/MethodsRemovedContract.sol +++ /dev/null @@ -1,13 +0,0 @@ -pragma solidity ^0.5.13; - -contract MethodsRemovedContract { - uint256 i = 3; - - function someMethod1(uint256 u) external { - i = u; - } - - function someMethod2(uint256 s) external pure returns (uint256) { - return s + 1; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_big_original/UnmodifiedContract.sol b/packages/protocol/test/resources/compatibility/contracts_big_original/UnmodifiedContract.sol deleted file mode 100644 index d7c1ef230..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_big_original/UnmodifiedContract.sol +++ /dev/null @@ -1,13 +0,0 @@ -pragma solidity ^0.5.13; - -contract UnmodifiedContract { - uint256 i = 3; - - function someMethod1(uint256 u) external { - i = u; - } - - function someMethod2(uint256 s) external pure returns (uint256) { - return s + 1; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_big_original_modified/ImplementationChangeContract.sol b/packages/protocol/test/resources/compatibility/contracts_big_original_modified/ImplementationChangeContract.sol deleted file mode 100644 index f8aa9e601..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_big_original_modified/ImplementationChangeContract.sol +++ /dev/null @@ -1,13 +0,0 @@ -pragma solidity ^0.5.13; - -contract ImplementationChangeContract { - uint256 i = 3; - - function someMethod1(uint256 u) external { - i = u + 7; - } - - function someMethod2(uint256 s) external pure returns (uint256) { - return s + 5; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_big_original_modified/MethodsAddedContract.sol b/packages/protocol/test/resources/compatibility/contracts_big_original_modified/MethodsAddedContract.sol deleted file mode 100644 index c6f10be8f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_big_original_modified/MethodsAddedContract.sol +++ /dev/null @@ -1,22 +0,0 @@ -pragma solidity ^0.5.13; - -contract MethodsAddedContract { - uint256 i = 3; - - function someMethod1(uint256 u) external { - i = u; - } - - function someMethod2(uint256 s) external pure returns (uint256) { - return s + 1; - } - - function newMethod1() external view returns (uint256) { - return i; - } - - function newMethod2(uint256 p) public payable returns (uint256) { - return i + 2 + p; - } - -} diff --git a/packages/protocol/test/resources/compatibility/contracts_big_original_modified/MethodsModifiedContract.sol b/packages/protocol/test/resources/compatibility/contracts_big_original_modified/MethodsModifiedContract.sol deleted file mode 100644 index 8ead4ca7f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_big_original_modified/MethodsModifiedContract.sol +++ /dev/null @@ -1,29 +0,0 @@ -pragma solidity ^0.5.13; - -contract MethodsModifiedContract { - string a = "value"; - uint256 i = 3; - - function someMethod1(uint256 u) public { - i = u; - } - - function someMethod2(uint256 s) external view returns (uint256) { - return i + s + 1; - } - - function someMethod3(uint256 s, string memory arg) - public - returns (uint256, string memory, uint256) - { - string memory res = string(abi.encodePacked(arg, a)); - a = arg; - return (s + 1, res, i); - } - - function someMethod4(uint256 s) public returns (uint256) { - i = s; - return s + 1; - } - -} diff --git a/packages/protocol/test/resources/compatibility/contracts_big_original_modified/MethodsRemovedContract.sol b/packages/protocol/test/resources/compatibility/contracts_big_original_modified/MethodsRemovedContract.sol deleted file mode 100644 index 256a08aaf..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_big_original_modified/MethodsRemovedContract.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -contract MethodsRemovedContract { - uint256 i = 3; - -} diff --git a/packages/protocol/test/resources/compatibility/contracts_big_original_modified/NewContract.sol b/packages/protocol/test/resources/compatibility/contracts_big_original_modified/NewContract.sol deleted file mode 100644 index ddc18462d..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_big_original_modified/NewContract.sol +++ /dev/null @@ -1,13 +0,0 @@ -pragma solidity ^0.5.13; - -contract NewContract { - uint256 i = 3; - - function someMethod1(uint256 u) external { - i = u; - } - - function someMethod2(uint256 s) external pure returns (uint256) { - return s + 1; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_big_original_modified/UnmodifiedContract.sol b/packages/protocol/test/resources/compatibility/contracts_big_original_modified/UnmodifiedContract.sol deleted file mode 100644 index d7c1ef230..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_big_original_modified/UnmodifiedContract.sol +++ /dev/null @@ -1,13 +0,0 @@ -pragma solidity ^0.5.13; - -contract UnmodifiedContract { - uint256 i = 3; - - function someMethod1(uint256 u) external { - i = u; - } - - function someMethod2(uint256 s) external pure returns (uint256) { - return s + 1; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_in_library_struct_mapping/Migrations.sol b/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_in_library_struct_mapping/Migrations.sol deleted file mode 100644 index d1008cca7..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_in_library_struct_mapping/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.13; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_in_library_struct_mapping/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_in_library_struct_mapping/TestContract.sol deleted file mode 100644 index 632344ac5..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_in_library_struct_mapping/TestContract.sol +++ /dev/null @@ -1,16 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - uint256 public x; - address public z; - - mapping(uint256 => Thing) thingMapping; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_in_library_struct_mapping/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_in_library_struct_mapping/TestLibrary.sol deleted file mode 100644 index 8f8bc25a5..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_in_library_struct_mapping/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 deprecated_field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_in_library_struct_mapping/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_in_library_struct_mapping/TestParent.sol deleted file mode 100644 index 00cd0b43f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_in_library_struct_mapping/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - mapping(uint256 => TestLibrary.Thing) thingMapping; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_in_struct/Migrations.sol b/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_in_struct/Migrations.sol deleted file mode 100644 index d1008cca7..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_in_struct/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.13; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_in_struct/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_in_struct/TestContract.sol deleted file mode 100644 index a431fa32c..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_in_struct/TestContract.sol +++ /dev/null @@ -1,16 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 deprecated_c; - } - - uint256 public x; - address public z; - - Thing public thing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_in_struct/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_in_struct/TestLibrary.sol deleted file mode 100644 index 419c91139..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_in_struct/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_in_struct/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_in_struct/TestParent.sol deleted file mode 100644 index 502ef0a9f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_in_struct/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - TestLibrary.Thing libraryThing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_variable/Migrations.sol b/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_variable/Migrations.sol deleted file mode 100644 index d1008cca7..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_variable/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.13; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_variable/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_variable/TestContract.sol deleted file mode 100644 index 6cb2fbe52..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_variable/TestContract.sol +++ /dev/null @@ -1,16 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - uint256 public x; - address public deprecated_z; - - Thing public thing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_variable/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_variable/TestLibrary.sol deleted file mode 100644 index 419c91139..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_variable/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_variable/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_variable/TestParent.sol deleted file mode 100644 index 502ef0a9f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_deprecated_prefixed_variable/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - TestLibrary.Thing libraryThing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_dynamic_to_fixed_array/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_dynamic_to_fixed_array/TestContract.sol deleted file mode 100644 index ae5d09e7b..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_dynamic_to_fixed_array/TestContract.sol +++ /dev/null @@ -1,20 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - uint256 public x; - address public z; - - uint128[5] fixedArray; - uint256[2] array; - mapping(uint256 => mapping(uint128 => address[])) map; - - Thing public thing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_dynamic_to_fixed_array/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_dynamic_to_fixed_array/TestLibrary.sol deleted file mode 100644 index 419c91139..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_dynamic_to_fixed_array/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_dynamic_to_fixed_array/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_dynamic_to_fixed_array/TestParent.sol deleted file mode 100644 index 502ef0a9f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_dynamic_to_fixed_array/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - TestLibrary.Thing libraryThing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_fixed_to_dynamic_array/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_fixed_to_dynamic_array/TestContract.sol deleted file mode 100644 index 862c4d69a..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_fixed_to_dynamic_array/TestContract.sol +++ /dev/null @@ -1,20 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - uint256 public x; - address public z; - - uint128[] fixedArray; - uint256[] array; - mapping(uint256 => mapping(uint128 => address[])) map; - - Thing public thing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_fixed_to_dynamic_array/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_fixed_to_dynamic_array/TestLibrary.sol deleted file mode 100644 index 419c91139..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_fixed_to_dynamic_array/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_fixed_to_dynamic_array/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_fixed_to_dynamic_array/TestParent.sol deleted file mode 100644 index 502ef0a9f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_fixed_to_dynamic_array/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - TestLibrary.Thing libraryThing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_inserted/Migrations.sol b/packages/protocol/test/resources/compatibility/contracts_inserted/Migrations.sol deleted file mode 100644 index d1008cca7..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_inserted/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.13; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_inserted/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_inserted/TestContract.sol deleted file mode 100644 index f36fade9c..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_inserted/TestContract.sol +++ /dev/null @@ -1,17 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - uint256 public x; - address public z; - uint256 public insertedVariable; - - Thing public thing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_inserted/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_inserted/TestLibrary.sol deleted file mode 100644 index 419c91139..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_inserted/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_inserted/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_inserted/TestParent.sol deleted file mode 100644 index 502ef0a9f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_inserted/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - TestLibrary.Thing libraryThing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_inserted_constant/Migrations.sol b/packages/protocol/test/resources/compatibility/contracts_inserted_constant/Migrations.sol deleted file mode 100644 index d1008cca7..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_inserted_constant/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.13; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_inserted_constant/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_inserted_constant/TestContract.sol deleted file mode 100644 index 9c8f38585..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_inserted_constant/TestContract.sol +++ /dev/null @@ -1,18 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - uint256 public constant INSERTED_CONSTANT = 42; - - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - uint256 public x; - address public z; - - Thing public thing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_inserted_constant/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_inserted_constant/TestLibrary.sol deleted file mode 100644 index 419c91139..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_inserted_constant/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_inserted_constant/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_inserted_constant/TestParent.sol deleted file mode 100644 index 502ef0a9f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_inserted_constant/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - TestLibrary.Thing libraryThing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_inserted_in_library_struct/Migrations.sol b/packages/protocol/test/resources/compatibility/contracts_inserted_in_library_struct/Migrations.sol deleted file mode 100644 index d1008cca7..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_inserted_in_library_struct/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.13; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_inserted_in_library_struct/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_inserted_in_library_struct/TestContract.sol deleted file mode 100644 index e20424e4d..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_inserted_in_library_struct/TestContract.sol +++ /dev/null @@ -1,16 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - uint256 public x; - address public z; - - Thing public thing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_inserted_in_library_struct/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_inserted_in_library_struct/TestLibrary.sol deleted file mode 100644 index 23182d925..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_inserted_in_library_struct/TestLibrary.sol +++ /dev/null @@ -1,9 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - uint128 insertedInLibraryStruct; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_inserted_in_library_struct/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_inserted_in_library_struct/TestParent.sol deleted file mode 100644 index 502ef0a9f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_inserted_in_library_struct/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - TestLibrary.Thing libraryThing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_inserted_in_library_struct_mapping/Migrations.sol b/packages/protocol/test/resources/compatibility/contracts_inserted_in_library_struct_mapping/Migrations.sol deleted file mode 100644 index d1008cca7..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_inserted_in_library_struct_mapping/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.13; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_inserted_in_library_struct_mapping/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_inserted_in_library_struct_mapping/TestContract.sol deleted file mode 100644 index 632344ac5..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_inserted_in_library_struct_mapping/TestContract.sol +++ /dev/null @@ -1,16 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - uint256 public x; - address public z; - - mapping(uint256 => Thing) thingMapping; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_inserted_in_library_struct_mapping/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_inserted_in_library_struct_mapping/TestLibrary.sol deleted file mode 100644 index 9b896161d..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_inserted_in_library_struct_mapping/TestLibrary.sol +++ /dev/null @@ -1,9 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - uint128 inserted; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_inserted_in_library_struct_mapping/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_inserted_in_library_struct_mapping/TestParent.sol deleted file mode 100644 index 00cd0b43f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_inserted_in_library_struct_mapping/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - mapping(uint256 => TestLibrary.Thing) thingMapping; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_inserted_in_struct/Migrations.sol b/packages/protocol/test/resources/compatibility/contracts_inserted_in_struct/Migrations.sol deleted file mode 100644 index d1008cca7..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_inserted_in_struct/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.13; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_inserted_in_struct/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_inserted_in_struct/TestContract.sol deleted file mode 100644 index 6c935645a..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_inserted_in_struct/TestContract.sol +++ /dev/null @@ -1,17 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - uint128 insertedInStruct; - } - - uint256 public x; - address public z; - - Thing public thing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_inserted_in_struct/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_inserted_in_struct/TestLibrary.sol deleted file mode 100644 index 419c91139..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_inserted_in_struct/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_inserted_in_struct/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_inserted_in_struct/TestParent.sol deleted file mode 100644 index 502ef0a9f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_inserted_in_struct/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - TestLibrary.Thing libraryThing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_inserted_in_struct_mapping/Migrations.sol b/packages/protocol/test/resources/compatibility/contracts_inserted_in_struct_mapping/Migrations.sol deleted file mode 100644 index d1008cca7..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_inserted_in_struct_mapping/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.13; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_inserted_in_struct_mapping/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_inserted_in_struct_mapping/TestContract.sol deleted file mode 100644 index a16494f71..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_inserted_in_struct_mapping/TestContract.sol +++ /dev/null @@ -1,18 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - uint128 inserted; - } - - uint256 public x; - address public z; - - mapping(uint256 => Thing) thingMapping; - Thing public myVariable; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_inserted_in_struct_mapping/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_inserted_in_struct_mapping/TestLibrary.sol deleted file mode 100644 index 419c91139..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_inserted_in_struct_mapping/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_inserted_in_struct_mapping/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_inserted_in_struct_mapping/TestParent.sol deleted file mode 100644 index 00cd0b43f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_inserted_in_struct_mapping/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - mapping(uint256 => TestLibrary.Thing) thingMapping; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_internal_mapping_source_changed/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_internal_mapping_source_changed/TestContract.sol deleted file mode 100644 index dd5adfa03..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_internal_mapping_source_changed/TestContract.sol +++ /dev/null @@ -1,20 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - uint256 public x; - address public z; - - uint128[5] fixedArray; - uint256[] array; - mapping(uint256 => mapping(uint256 => address[])) map; - - Thing public thing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_internal_mapping_source_changed/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_internal_mapping_source_changed/TestLibrary.sol deleted file mode 100644 index 419c91139..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_internal_mapping_source_changed/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_internal_mapping_source_changed/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_internal_mapping_source_changed/TestParent.sol deleted file mode 100644 index 502ef0a9f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_internal_mapping_source_changed/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - TestLibrary.Thing libraryThing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_linked_libraries/LinkedLibrary1.sol b/packages/protocol/test/resources/compatibility/contracts_linked_libraries/LinkedLibrary1.sol deleted file mode 100644 index 8facffbec..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_linked_libraries/LinkedLibrary1.sol +++ /dev/null @@ -1,15 +0,0 @@ -pragma solidity ^0.5.3; - -library LinkedLibrary1 { - struct Struct { - uint256 field; - } - - function get(Struct storage s) public view returns (uint256) { - return s.field; - } - - function increase(Struct storage s) public { - s.field += 1; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_linked_libraries/LinkedLibrary2.sol b/packages/protocol/test/resources/compatibility/contracts_linked_libraries/LinkedLibrary2.sol deleted file mode 100644 index 67ec94ab3..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_linked_libraries/LinkedLibrary2.sol +++ /dev/null @@ -1,19 +0,0 @@ -pragma solidity ^0.5.3; - -import "./LinkedLibrary3.sol"; - -library LinkedLibrary2 { - using LinkedLibrary3 for LinkedLibrary3.Struct; - - struct Struct { - LinkedLibrary3.Struct s; - } - - function get(Struct storage s) public view returns (uint256) { - return s.s.get(); - } - - function increase(Struct storage s) public { - s.s.increase(); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_linked_libraries/LinkedLibrary3.sol b/packages/protocol/test/resources/compatibility/contracts_linked_libraries/LinkedLibrary3.sol deleted file mode 100644 index 002561e97..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_linked_libraries/LinkedLibrary3.sol +++ /dev/null @@ -1,18 +0,0 @@ -pragma solidity ^0.5.3; - -library LinkedLibrary3 { - struct Struct { - uint256 field; - } - - function get(Struct storage s) public view returns (uint256) { - return s.field; - } - - function increase(Struct storage s) public { - if (s.field == 0) { - s.field = 1; - } - s.field *= 2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_linked_libraries/Migrations.sol b/packages/protocol/test/resources/compatibility/contracts_linked_libraries/Migrations.sol deleted file mode 100644 index b61987df6..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_linked_libraries/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.3; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_linked_libraries/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_linked_libraries/TestContract.sol deleted file mode 100644 index 7df222596..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_linked_libraries/TestContract.sol +++ /dev/null @@ -1,25 +0,0 @@ -pragma solidity ^0.5.3; - -import "./LinkedLibrary1.sol"; -import "./LinkedLibrary2.sol"; - -contract TestContract { - using LinkedLibrary1 for LinkedLibrary1.Struct; - using LinkedLibrary2 for LinkedLibrary2.Struct; - - LinkedLibrary1.Struct s1; - LinkedLibrary2.Struct s2; - - function get1() external view returns (uint256) { - return s1.get(); - } - - function get2() external view returns (uint256) { - return s2.get(); - } - - function doIncreases() external { - s1.increase(); - s2.increase(); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_contract/LinkedLibrary1.sol b/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_contract/LinkedLibrary1.sol deleted file mode 100644 index 8facffbec..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_contract/LinkedLibrary1.sol +++ /dev/null @@ -1,15 +0,0 @@ -pragma solidity ^0.5.3; - -library LinkedLibrary1 { - struct Struct { - uint256 field; - } - - function get(Struct storage s) public view returns (uint256) { - return s.field; - } - - function increase(Struct storage s) public { - s.field += 1; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_contract/LinkedLibrary2.sol b/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_contract/LinkedLibrary2.sol deleted file mode 100644 index 67ec94ab3..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_contract/LinkedLibrary2.sol +++ /dev/null @@ -1,19 +0,0 @@ -pragma solidity ^0.5.3; - -import "./LinkedLibrary3.sol"; - -library LinkedLibrary2 { - using LinkedLibrary3 for LinkedLibrary3.Struct; - - struct Struct { - LinkedLibrary3.Struct s; - } - - function get(Struct storage s) public view returns (uint256) { - return s.s.get(); - } - - function increase(Struct storage s) public { - s.s.increase(); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_contract/LinkedLibrary3.sol b/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_contract/LinkedLibrary3.sol deleted file mode 100644 index 002561e97..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_contract/LinkedLibrary3.sol +++ /dev/null @@ -1,18 +0,0 @@ -pragma solidity ^0.5.3; - -library LinkedLibrary3 { - struct Struct { - uint256 field; - } - - function get(Struct storage s) public view returns (uint256) { - return s.field; - } - - function increase(Struct storage s) public { - if (s.field == 0) { - s.field = 1; - } - s.field *= 2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_contract/Migrations.sol b/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_contract/Migrations.sol deleted file mode 100644 index b61987df6..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_contract/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.3; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_contract/Proxy.sol b/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_contract/Proxy.sol deleted file mode 100644 index 36bfbcf9a..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_contract/Proxy.sol +++ /dev/null @@ -1,163 +0,0 @@ -pragma solidity ^0.5.13; -/* solhint-disable no-inline-assembly, no-complex-fallback, avoid-low-level-calls */ - -import "openzeppelin-solidity/contracts/utils/Address.sol"; - -/** - * @title A Proxy utilizing the Unstructured Storage pattern. - */ -contract Proxy { - // Used to store the address of the owner. - bytes32 private constant OWNER_POSITION = bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1); - // Used to store the address of the implementation contract. - bytes32 private constant IMPLEMENTATION_POSITION = bytes32( - uint256(keccak256("eip1967.proxy.implementation")) - 1 - ); - - event OwnerSet(address indexed owner); - event ImplementationSet(address indexed implementation); - - constructor() public { - _setOwner(msg.sender); - } - - /** - * @notice Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(msg.sender == _getOwner(), "sender was not owner"); - _; - } - - /** - * @notice Delegates calls to the implementation contract. - */ - function() external payable { - bytes32 implementationPosition = IMPLEMENTATION_POSITION; - - address implementationAddress; - - // Load the address of the implementation contract from an explicit storage slot. - assembly { - implementationAddress := sload(implementationPosition) - } - - // Avoid checking if address is a contract or executing delegated call when - // implementation address is 0x0 - require(implementationAddress != address(0), "No Implementation set"); - require(Address.isContract(implementationAddress), "Invalid contract address"); - - assembly { - // Extract the position of the transaction data (i.e. function ID and arguments). - let newCallDataPosition := mload(0x40) - mstore(0x40, add(newCallDataPosition, calldatasize)) - calldatacopy(newCallDataPosition, 0, calldatasize) - - // Call the smart contract at `implementationAddress` in the context of the proxy contract, - // with the same msg.sender and value. - let delegatecallSuccess := delegatecall( - gas, - implementationAddress, - newCallDataPosition, - calldatasize, - 0, - 0 - ) - - // Copy the return value of the call so it can be returned. - let returnDataSize := returndatasize - let returnDataPosition := mload(0x40) - mstore(0x40, add(returnDataPosition, returnDataSize)) - returndatacopy(returnDataPosition, 0, returnDataSize) - - // Revert or return depending on whether or not the call was successful. - switch delegatecallSuccess - case 0 { - revert(returnDataPosition, returnDataSize) - } - default { - return(returnDataPosition, returnDataSize) - } - } - } - - /** - * @notice Transfers ownership of Proxy to a new owner. - * @param newOwner Address of the new owner account. - */ - function _transferOwnership(address newOwner) external onlyOwner { - _setOwner(newOwner); - } - - /** - * @notice Sets the address of the implementation contract and calls into it. - * @param implementation Address of the new target contract. - * @param callbackData The abi-encoded function call to perform in the implementation - * contract. - * @dev Throws if the initialization callback fails. - * @dev If the target contract does not need initialization, use - * setImplementation instead. - */ - function _setAndInitializeImplementation(address implementation, bytes calldata callbackData) - external - payable - onlyOwner - { - _setImplementation(implementation); - bool success; - bytes memory returnValue; - (success, returnValue) = implementation.delegatecall(callbackData); - require(success, "initialization callback failed"); - } - - /** - * @notice Returns the implementation address. - */ - function _getImplementation() external view returns (address implementation) { - bytes32 implementationPosition = IMPLEMENTATION_POSITION; - // Load the address of the implementation contract from an explicit storage slot. - assembly { - implementation := sload(implementationPosition) - } - } - - /** - * @notice Sets the address of the implementation contract. - * @param implementation Address of the new target contract. - * @dev If the target contract needs to be initialized, call - * setAndInitializeImplementation instead. - */ - function _setImplementation(address implementation) public onlyOwner { - bytes32 implementationPosition = IMPLEMENTATION_POSITION; - - require(Address.isContract(implementation), "Invalid contract address"); - - // Store the address of the implementation contract in an explicit storage slot. - assembly { - sstore(implementationPosition, implementation) - } - - emit ImplementationSet(implementation); - } - - /** - * @notice Returns the Proxy owner's address. - */ - function _getOwner() public view returns (address owner) { - bytes32 position = OWNER_POSITION; - // Load the address of the contract owner from an explicit storage slot. - assembly { - owner := sload(position) - } - } - - function _setOwner(address newOwner) private { - require(newOwner != address(0), "owner cannot be 0"); - bytes32 position = OWNER_POSITION; - // Store the address of the contract owner in an explicit storage slot. - assembly { - sstore(position, newOwner) - } - emit OwnerSet(newOwner); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_contract/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_contract/TestContract.sol deleted file mode 100644 index 4449c10dd..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_contract/TestContract.sol +++ /dev/null @@ -1,25 +0,0 @@ -pragma solidity ^0.5.3; - -import "./LinkedLibrary1.sol"; -import "./LinkedLibrary2.sol"; - -contract TestContract { - using LinkedLibrary1 for LinkedLibrary1.Struct; - using LinkedLibrary2 for LinkedLibrary2.Struct; - - LinkedLibrary1.Struct s1; - LinkedLibrary2.Struct s2; - - function get1() external view returns (uint256) { - return s1.get() + 1; - } - - function get2() external view returns (uint256) { - return s2.get(); - } - - function doIncreases() external { - s1.increase(); - s2.increase(); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_contract/TestContractProxy.sol b/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_contract/TestContractProxy.sol deleted file mode 100644 index 298c3ffa2..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_contract/TestContractProxy.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.5.13; - -import "./Proxy.sol"; - -/* solhint-disable-next-line no-empty-blocks */ -contract TestContractProxy is Proxy {} diff --git a/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_lib/LinkedLibrary1.sol b/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_lib/LinkedLibrary1.sol deleted file mode 100644 index 8facffbec..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_lib/LinkedLibrary1.sol +++ /dev/null @@ -1,15 +0,0 @@ -pragma solidity ^0.5.3; - -library LinkedLibrary1 { - struct Struct { - uint256 field; - } - - function get(Struct storage s) public view returns (uint256) { - return s.field; - } - - function increase(Struct storage s) public { - s.field += 1; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_lib/LinkedLibrary2.sol b/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_lib/LinkedLibrary2.sol deleted file mode 100644 index 67ec94ab3..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_lib/LinkedLibrary2.sol +++ /dev/null @@ -1,19 +0,0 @@ -pragma solidity ^0.5.3; - -import "./LinkedLibrary3.sol"; - -library LinkedLibrary2 { - using LinkedLibrary3 for LinkedLibrary3.Struct; - - struct Struct { - LinkedLibrary3.Struct s; - } - - function get(Struct storage s) public view returns (uint256) { - return s.s.get(); - } - - function increase(Struct storage s) public { - s.s.increase(); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_lib/LinkedLibrary3.sol b/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_lib/LinkedLibrary3.sol deleted file mode 100644 index 6fad50b40..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_lib/LinkedLibrary3.sol +++ /dev/null @@ -1,18 +0,0 @@ -pragma solidity ^0.5.3; - -library LinkedLibrary3 { - struct Struct { - uint256 field; - } - - function get(Struct storage s) public view returns (uint256) { - return s.field; - } - - function increase(Struct storage s) public { - if (s.field == 0) { - s.field = 1; - } - s.field *= 3; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_lib/Migrations.sol b/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_lib/Migrations.sol deleted file mode 100644 index b61987df6..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_lib/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.3; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_lib/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_lib/TestContract.sol deleted file mode 100644 index 7df222596..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_linked_libraries_upgraded_lib/TestContract.sol +++ /dev/null @@ -1,25 +0,0 @@ -pragma solidity ^0.5.3; - -import "./LinkedLibrary1.sol"; -import "./LinkedLibrary2.sol"; - -contract TestContract { - using LinkedLibrary1 for LinkedLibrary1.Struct; - using LinkedLibrary2 for LinkedLibrary2.Struct; - - LinkedLibrary1.Struct s1; - LinkedLibrary2.Struct s2; - - function get1() external view returns (uint256) { - return s1.get(); - } - - function get2() external view returns (uint256) { - return s2.get(); - } - - function doIncreases() external { - s1.increase(); - s2.increase(); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_longer_fixed_array/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_longer_fixed_array/TestContract.sol deleted file mode 100644 index 9e9dfe86c..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_longer_fixed_array/TestContract.sol +++ /dev/null @@ -1,20 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - uint256 public x; - address public z; - - uint128[6] fixedArray; - uint256[] array; - mapping(uint256 => mapping(uint128 => address[])) map; - - Thing public thing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_longer_fixed_array/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_longer_fixed_array/TestLibrary.sol deleted file mode 100644 index 419c91139..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_longer_fixed_array/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_longer_fixed_array/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_longer_fixed_array/TestParent.sol deleted file mode 100644 index 502ef0a9f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_longer_fixed_array/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - TestLibrary.Thing libraryThing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_mapping_source_changed/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_mapping_source_changed/TestContract.sol deleted file mode 100644 index feb37e866..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_mapping_source_changed/TestContract.sol +++ /dev/null @@ -1,20 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - uint256 public x; - address public z; - - uint128[5] fixedArray; - uint256[] array; - mapping(uint128 => mapping(uint128 => address[])) map; - - Thing public thing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_mapping_source_changed/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_mapping_source_changed/TestLibrary.sol deleted file mode 100644 index 419c91139..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_mapping_source_changed/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_mapping_source_changed/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_mapping_source_changed/TestParent.sol deleted file mode 100644 index 502ef0a9f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_mapping_source_changed/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - TestLibrary.Thing libraryThing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_mapping_target_changed/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_mapping_target_changed/TestContract.sol deleted file mode 100644 index 46fda2329..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_mapping_target_changed/TestContract.sol +++ /dev/null @@ -1,20 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - uint256 public x; - address public z; - - uint128[5] fixedArray; - uint256[] array; - mapping(uint256 => mapping(uint128 => bool)) map; - - Thing public thing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_mapping_target_changed/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_mapping_target_changed/TestLibrary.sol deleted file mode 100644 index 419c91139..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_mapping_target_changed/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_mapping_target_changed/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_mapping_target_changed/TestParent.sol deleted file mode 100644 index 502ef0a9f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_mapping_target_changed/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - TestLibrary.Thing libraryThing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_metadata_changed/Migrations.sol b/packages/protocol/test/resources/compatibility/contracts_metadata_changed/Migrations.sol deleted file mode 100644 index d1008cca7..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_metadata_changed/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.13; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_metadata_changed/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_metadata_changed/TestContract.sol deleted file mode 100644 index 1d8ee2ba9..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_metadata_changed/TestContract.sol +++ /dev/null @@ -1,17 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - uint256 public x; - address public z; - - // Adding a comment should trigger a metadata change. - Thing public thing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_metadata_changed/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_metadata_changed/TestLibrary.sol deleted file mode 100644 index 419c91139..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_metadata_changed/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_metadata_changed/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_metadata_changed/TestParent.sol deleted file mode 100644 index 502ef0a9f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_metadata_changed/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - TestLibrary.Thing libraryThing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_original/Migrations.sol b/packages/protocol/test/resources/compatibility/contracts_original/Migrations.sol deleted file mode 100644 index d1008cca7..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_original/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.13; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_original/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_original/TestContract.sol deleted file mode 100644 index e20424e4d..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_original/TestContract.sol +++ /dev/null @@ -1,16 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - uint256 public x; - address public z; - - Thing public thing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_original/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_original/TestLibrary.sol deleted file mode 100644 index 419c91139..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_original/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_original/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_original/TestParent.sol deleted file mode 100644 index 502ef0a9f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_original/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - TestLibrary.Thing libraryThing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_original_complex/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_original_complex/TestContract.sol deleted file mode 100644 index 222e1d29a..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_original_complex/TestContract.sol +++ /dev/null @@ -1,20 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - uint256 public x; - address public z; - - uint128[5] fixedArray; - uint256[] array; - mapping(uint256 => mapping(uint128 => address[])) map; - - Thing public thing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_original_complex/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_original_complex/TestLibrary.sol deleted file mode 100644 index 419c91139..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_original_complex/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_original_complex/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_original_complex/TestParent.sol deleted file mode 100644 index 502ef0a9f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_original_complex/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - TestLibrary.Thing libraryThing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_original_copy/Migrations.sol b/packages/protocol/test/resources/compatibility/contracts_original_copy/Migrations.sol deleted file mode 100644 index d1008cca7..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_original_copy/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.13; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_original_copy/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_original_copy/TestContract.sol deleted file mode 100644 index e20424e4d..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_original_copy/TestContract.sol +++ /dev/null @@ -1,16 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - uint256 public x; - address public z; - - Thing public thing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_original_copy/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_original_copy/TestLibrary.sol deleted file mode 100644 index 419c91139..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_original_copy/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_original_copy/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_original_copy/TestParent.sol deleted file mode 100644 index 502ef0a9f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_original_copy/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - TestLibrary.Thing libraryThing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_original_struct_in_mapping/Migrations.sol b/packages/protocol/test/resources/compatibility/contracts_original_struct_in_mapping/Migrations.sol deleted file mode 100644 index d1008cca7..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_original_struct_in_mapping/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.13; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_original_struct_in_mapping/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_original_struct_in_mapping/TestContract.sol deleted file mode 100644 index 632344ac5..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_original_struct_in_mapping/TestContract.sol +++ /dev/null @@ -1,16 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - uint256 public x; - address public z; - - mapping(uint256 => Thing) thingMapping; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_original_struct_in_mapping/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_original_struct_in_mapping/TestLibrary.sol deleted file mode 100644 index 419c91139..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_original_struct_in_mapping/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_original_struct_in_mapping/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_original_struct_in_mapping/TestParent.sol deleted file mode 100644 index 00cd0b43f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_original_struct_in_mapping/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - mapping(uint256 => TestLibrary.Thing) thingMapping; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_removed/Migrations.sol b/packages/protocol/test/resources/compatibility/contracts_removed/Migrations.sol deleted file mode 100644 index d1008cca7..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_removed/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.13; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_removed/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_removed/TestContract.sol deleted file mode 100644 index bf4c3bbd3..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_removed/TestContract.sol +++ /dev/null @@ -1,16 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - // uint256 public x; - address public z; - - Thing public thing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_removed/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_removed/TestLibrary.sol deleted file mode 100644 index 419c91139..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_removed/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_removed/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_removed/TestParent.sol deleted file mode 100644 index 502ef0a9f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_removed/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - TestLibrary.Thing libraryThing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_removed_from_library_struct/Migrations.sol b/packages/protocol/test/resources/compatibility/contracts_removed_from_library_struct/Migrations.sol deleted file mode 100644 index d1008cca7..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_removed_from_library_struct/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.13; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_removed_from_library_struct/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_removed_from_library_struct/TestContract.sol deleted file mode 100644 index e20424e4d..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_removed_from_library_struct/TestContract.sol +++ /dev/null @@ -1,16 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - uint256 public x; - address public z; - - Thing public thing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_removed_from_library_struct/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_removed_from_library_struct/TestLibrary.sol deleted file mode 100644 index e2bac5b01..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_removed_from_library_struct/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - // uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_removed_from_library_struct/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_removed_from_library_struct/TestParent.sol deleted file mode 100644 index 502ef0a9f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_removed_from_library_struct/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - TestLibrary.Thing libraryThing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_removed_from_parent/Migrations.sol b/packages/protocol/test/resources/compatibility/contracts_removed_from_parent/Migrations.sol deleted file mode 100644 index d1008cca7..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_removed_from_parent/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.13; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_removed_from_parent/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_removed_from_parent/TestContract.sol deleted file mode 100644 index e20424e4d..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_removed_from_parent/TestContract.sol +++ /dev/null @@ -1,16 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - uint256 public x; - address public z; - - Thing public thing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_removed_from_parent/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_removed_from_parent/TestLibrary.sol deleted file mode 100644 index 419c91139..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_removed_from_parent/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_removed_from_parent/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_removed_from_parent/TestParent.sol deleted file mode 100644 index df3a3355d..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_removed_from_parent/TestParent.sol +++ /dev/null @@ -1,15 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - // TestLibrary.Thing libraryThing; - -} diff --git a/packages/protocol/test/resources/compatibility/contracts_removed_from_struct/Migrations.sol b/packages/protocol/test/resources/compatibility/contracts_removed_from_struct/Migrations.sol deleted file mode 100644 index d1008cca7..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_removed_from_struct/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.13; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_removed_from_struct/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_removed_from_struct/TestContract.sol deleted file mode 100644 index 58da34ec0..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_removed_from_struct/TestContract.sol +++ /dev/null @@ -1,16 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - // uint128 b; - uint128 c; - } - - uint256 public x; - address public z; - - Thing public thing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_removed_from_struct/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_removed_from_struct/TestLibrary.sol deleted file mode 100644 index 419c91139..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_removed_from_struct/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_removed_from_struct/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_removed_from_struct/TestParent.sol deleted file mode 100644 index 502ef0a9f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_removed_from_struct/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - TestLibrary.Thing libraryThing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_shorter_fixed_array/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_shorter_fixed_array/TestContract.sol deleted file mode 100644 index 0bbd1d226..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_shorter_fixed_array/TestContract.sol +++ /dev/null @@ -1,20 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - uint256 public x; - address public z; - - uint128[4] fixedArray; - uint256[] array; - mapping(uint256 => mapping(uint128 => address[])) map; - - Thing public thing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_shorter_fixed_array/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_shorter_fixed_array/TestLibrary.sol deleted file mode 100644 index 419c91139..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_shorter_fixed_array/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_shorter_fixed_array/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_shorter_fixed_array/TestParent.sol deleted file mode 100644 index 502ef0a9f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_shorter_fixed_array/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - TestLibrary.Thing libraryThing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_typechange/Migrations.sol b/packages/protocol/test/resources/compatibility/contracts_typechange/Migrations.sol deleted file mode 100644 index d1008cca7..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_typechange/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.13; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_typechange/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_typechange/TestContract.sol deleted file mode 100644 index 5855f76af..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_typechange/TestContract.sol +++ /dev/null @@ -1,16 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - bytes32 public x; - address public z; - - Thing public thing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_typechange/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_typechange/TestLibrary.sol deleted file mode 100644 index 419c91139..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_typechange/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_typechange/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_typechange/TestParent.sol deleted file mode 100644 index 502ef0a9f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_typechange/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - TestLibrary.Thing libraryThing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_typechange_in_library_struct/Migrations.sol b/packages/protocol/test/resources/compatibility/contracts_typechange_in_library_struct/Migrations.sol deleted file mode 100644 index d1008cca7..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_typechange_in_library_struct/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.13; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_typechange_in_library_struct/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_typechange_in_library_struct/TestContract.sol deleted file mode 100644 index e20424e4d..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_typechange_in_library_struct/TestContract.sol +++ /dev/null @@ -1,16 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - uint256 public x; - address public z; - - Thing public thing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_typechange_in_library_struct/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_typechange_in_library_struct/TestLibrary.sol deleted file mode 100644 index 08a6a9ef7..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_typechange_in_library_struct/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - bool field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_typechange_in_library_struct/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_typechange_in_library_struct/TestParent.sol deleted file mode 100644 index 502ef0a9f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_typechange_in_library_struct/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - TestLibrary.Thing libraryThing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_typechange_in_parent/Migrations.sol b/packages/protocol/test/resources/compatibility/contracts_typechange_in_parent/Migrations.sol deleted file mode 100644 index d1008cca7..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_typechange_in_parent/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.13; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_typechange_in_parent/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_typechange_in_parent/TestContract.sol deleted file mode 100644 index e20424e4d..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_typechange_in_parent/TestContract.sol +++ /dev/null @@ -1,16 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - uint256 public x; - address public z; - - Thing public thing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_typechange_in_parent/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_typechange_in_parent/TestLibrary.sol deleted file mode 100644 index 419c91139..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_typechange_in_parent/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_typechange_in_parent/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_typechange_in_parent/TestParent.sol deleted file mode 100644 index 622b90238..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_typechange_in_parent/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - string private q; - - TestLibrary.Thing libraryThing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_typechange_in_struct/Migrations.sol b/packages/protocol/test/resources/compatibility/contracts_typechange_in_struct/Migrations.sol deleted file mode 100644 index d1008cca7..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_typechange_in_struct/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.13; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_typechange_in_struct/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_typechange_in_struct/TestContract.sol deleted file mode 100644 index a619eb0cf..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_typechange_in_struct/TestContract.sol +++ /dev/null @@ -1,16 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - address a; - uint128 b; - uint128 c; - } - - uint256 public x; - address public z; - - Thing public thing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_typechange_in_struct/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_typechange_in_struct/TestLibrary.sol deleted file mode 100644 index 419c91139..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_typechange_in_struct/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_typechange_in_struct/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_typechange_in_struct/TestParent.sol deleted file mode 100644 index 502ef0a9f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_typechange_in_struct/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - TestLibrary.Thing libraryThing; -} diff --git a/packages/protocol/test/resources/compatibility/contracts_versioned/Migrations.sol b/packages/protocol/test/resources/compatibility/contracts_versioned/Migrations.sol deleted file mode 100644 index d1008cca7..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_versioned/Migrations.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.5.13; - -contract Migrations { - address public owner; - uint256 public last_completed_migration; // solhint-disable var-name-mixedcase - - modifier restricted() { - if (msg.sender == owner) _; - } - - constructor() public { - owner = msg.sender; - } - - function setCompleted(uint256 completed) external restricted { - last_completed_migration = completed; // solhint-disable var-name-mixedcase - } - - // solhint-disable-next-line func-param-name-mixedcase - function upgrade(address new_address) external restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_versioned/TestContract.sol b/packages/protocol/test/resources/compatibility/contracts_versioned/TestContract.sol deleted file mode 100644 index d5505d482..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_versioned/TestContract.sol +++ /dev/null @@ -1,20 +0,0 @@ -pragma solidity ^0.5.13; - -import "./TestParent.sol"; - -contract TestContract is TestParent { - struct Thing { - uint128 a; - uint128 b; - uint128 c; - } - - uint256 public x; - address public z; - - Thing public thing; - - function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { - return (1, 2, 3, 4); - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_versioned/TestLibrary.sol b/packages/protocol/test/resources/compatibility/contracts_versioned/TestLibrary.sol deleted file mode 100644 index 419c91139..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_versioned/TestLibrary.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity ^0.5.13; - -library TestLibrary { - struct Thing { - uint8 field1; - uint16 field2; - } -} diff --git a/packages/protocol/test/resources/compatibility/contracts_versioned/TestParent.sol b/packages/protocol/test/resources/compatibility/contracts_versioned/TestParent.sol deleted file mode 100644 index 502ef0a9f..000000000 --- a/packages/protocol/test/resources/compatibility/contracts_versioned/TestParent.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.13; - -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; - -import "./TestLibrary.sol"; - -contract TestParent is Ownable { - using TestLibrary for TestLibrary.Thing; - - uint256 private p; - address private q; - - TestLibrary.Thing libraryThing; -} diff --git a/packages/protocol/test/teardown.ts b/packages/protocol/test/teardown.ts deleted file mode 100644 index 0f6d61ace..000000000 --- a/packages/protocol/test/teardown.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Global teardown for coverage -after(async () => { - if ((global as any).coverageSubprovider) { - await (global as any).coverageSubprovider.writeCoverageAsync() - } -}) diff --git a/packages/protocol/truffle-config-parent.js b/packages/protocol/truffle-config-parent.js deleted file mode 100644 index b5595f177..000000000 --- a/packages/protocol/truffle-config-parent.js +++ /dev/null @@ -1,223 +0,0 @@ -/* tslint:disable: object-literal-sort-keys */ -require('ts-node/register') -const ProviderEngine = require('web3-provider-engine') -const WebsocketSubprovider = require('web3-provider-engine/subproviders/websocket.js') -const { TruffleArtifactAdapter } = require('@0x/sol-trace') -const { CoverageSubprovider } = require('@0x/sol-coverage') -var Web3 = require('web3') -var net = require('net') - -const argv = require('minimist')(process.argv.slice(2), { - string: ['truffle_override', 'network'], - boolean: ['reset'], -}) - -const ALFAJORES_NETWORKID = 44787 -const BAKLAVA_NETWORKID = 62320 -const BAKLAVASTAGING_NETWORKID = 31420 -const CANNOLI_NETWORKID = 17323 - -const OG_FROM = '0xfeE1a22F43BeeCB912B5a4912ba87527682ef0fC' -const DEVELOPMENT_FROM = '0x5409ed021d9299bf6814279a6a1411a7e866a631' -const INTEGRATION_FROM = '0x47e172F6CfB6c7D01C1574fa3E2Be7CC73269D95' -const INTEGRATION_TESTING_FROM = '0x47e172F6CfB6c7D01C1574fa3E2Be7CC73269D95' -const ALFAJORESSTAGING_FROM = '0xf4314cb9046bece6aa54bb9533155434d0c76909' -const ALFAJORES_FROM = '0x456f41406B32c45D59E539e4BBA3D7898c3584dA' -const PILOT_FROM = '0x387bCb16Bfcd37AccEcF5c9eB2938E30d3aB8BF2' -const PILOTSTAGING_FROM = '0x545DEBe3030B570731EDab192640804AC8Cf65CA' -const RC0_FROM = '0x469be98FE71AFf8F6e7f64F9b732e28A03596B5C' -const BAKLAVA_FROM = '0x0Cc59Ed03B3e763c02d54D695FFE353055f1502D' -const BAKLAVASTAGING_FROM = '0x4588ABb84e1BBEFc2BcF4b2296F785fB7AD9F285' -const STAGING_FROM = '0x4e3d385ecdee402da395a3b18575b05cc5e8ff21' -const CANNOLI_FROM = '0x8C174E896A85E487aa895865657b78Ea64879dC7' // validator zero - -const gasLimit = 13000000 -const hostAddress = process.env.CELO_NODE_ADDRESS || '127.0.0.1' -const hostPort = parseInt(process.env.CELO_NODE_PORT || '8545') - -const defaultConfig = { - host: hostAddress, - port: hostPort, - network_id: 1101, - from: OG_FROM, - gas: gasLimit, - gasPrice: 100000000000, - // maxFeePerGas: 975000000, -} - -const freeGasConfig = { ...defaultConfig, ...{ gasPrice: 0 } } - -// ipcProvider returns a function to create an IPC provider when called. -// Use by adding `provider: ipcProvider(...)` to any of the configs below. -function ipcProvider(path) { - return () => new Web3.providers.IpcProvider(path, net) -} - -// Here to avoid recreating it each time -let coverageProvider = null - -const fornoUrls = { - alfajores: 'https://alfajores-forno.celo-testnet.org', - baklava: 'https://baklava-forno.celo-testnet.org', - rc1: 'https://forno.celo.org', - mainnet: 'https://forno.celo.org', - staging: 'https://staging-forno.celo-networks-dev.org', -} - -const networks = { - development: { - ...defaultConfig, - from: DEVELOPMENT_FROM, - gasPrice: 0, - gas: gasLimit, - defaultBalance: 200000000, - mnemonic: 'concert load couple harbor equip island argue ramp clarify fence smart topic', - }, - rc0: { - host: hostAddress, - port: hostPort, - from: RC0_FROM, - network_id: 200312, - gasPrice: 100000000000, - }, - rc1: { - host: '127.0.0.1', - port: 8545, - from: '0xE23a4c6615669526Ab58E9c37088bee4eD2b2dEE', - network_id: 42220, - gas: gasLimit, - gasPrice: 10000000000, - }, - coverage: { - host: 'localhost', - network_id: '*', - gasPrice: 0, - gas: gasLimit, - from: DEVELOPMENT_FROM, - provider: function () { - if (coverageProvider == null) { - coverageProvider = new ProviderEngine() - - const projectRoot = '' - const artifactAdapter = new TruffleArtifactAdapter(projectRoot, SOLC_VERSION) - global.coverageSubprovider = new CoverageSubprovider(artifactAdapter, DEVELOPMENT_FROM, { - isVerbose: true, - ignoreFilesGlobs: [ - // Proxies - '**/*Proxy.sol', - - // Test contracts - '**/test/*.sol', - - // Interfaces - '**/interfaces/*.sol', - ], - }) - coverageProvider.addProvider(global.coverageSubprovider) - - coverageProvider.addProvider( - new WebsocketSubprovider({ - rpcUrl: `http://localhost:${defaultConfig.port}`, - debug: false, - }) - ) - - coverageProvider.start((err) => { - if (err !== undefined) { - // tslint:disable-next-line: no-console - console.error(err) - process.exit(1) - } - }) - /** - * HACK: Truffle providers should have `send` function, while `ProviderEngine` creates providers with `sendAsync`, - * but it can be easily fixed by assigning `sendAsync` to `send`. - */ - coverageProvider.send = coverageProvider.sendAsync.bind(coverageProvider) - } - return coverageProvider - }, - }, - testnet_prod: defaultConfig, - - // New testnets - integration: { - ...defaultConfig, - from: INTEGRATION_FROM, - }, - testing: { - ...defaultConfig, - from: INTEGRATION_TESTING_FROM, - network_id: 1101, - }, - argentinastaging: freeGasConfig, - argentinaproduction: freeGasConfig, - - alfajoresstaging: { - ...defaultConfig, - from: ALFAJORESSTAGING_FROM, - }, - - alfajores: { - ...defaultConfig, - network_id: ALFAJORES_NETWORKID, - from: ALFAJORES_FROM, - }, - - cannoli: { - ...defaultConfig, - network_id: CANNOLI_NETWORKID, - from: CANNOLI_FROM, - }, - - pilot: { - ...defaultConfig, - from: PILOT_FROM, - }, - pilotstaging: { - ...defaultConfig, - from: PILOTSTAGING_FROM, - }, - baklava: { - ...defaultConfig, - from: BAKLAVA_FROM, - network_id: BAKLAVA_NETWORKID, - }, - baklavastaging: { - ...defaultConfig, - from: BAKLAVASTAGING_FROM, - network_id: BAKLAVASTAGING_NETWORKID, - }, - staging: { - ...defaultConfig, - from: STAGING_FROM, - }, -} -// Equivalent -networks.mainnet = networks.rc1 - -// If an override was provided, apply it. -// If the network is missing from networks, start with the default config. -if (argv.truffle_override || !(argv.network in networks)) { - const configOverride = argv.truffle_override ? JSON.parse(argv.truffle_override) : {} - if (argv.network in networks) { - networks[argv.network] = { ...networks[argv.network], ...configOverride } - } else { - networks[argv.network] = { ...defaultConfig, ...configOverride } - } -} - -if (process.argv.includes('--forno')) { - if (!fornoUrls[argv.network]) { - console.log(`Forno URL for network ${argv.network} not known!`) - process.exit(1) - } - - networks[argv.network].host = undefined - networks[argv.network].port = undefined - networks[argv.network].provider = function () { - return new Web3.providers.HttpProvider(fornoUrls[argv.network]) - } -} - -module.exports = { networks: networks } diff --git a/packages/protocol/truffle-config.js b/packages/protocol/truffle-config.js deleted file mode 100644 index 530daeacd..000000000 --- a/packages/protocol/truffle-config.js +++ /dev/null @@ -1,47 +0,0 @@ -const SOLC_VERSION = '0.5.13' - -const parent = require('./truffle-config-parent.js') -const networks = { ...parent.networks } -const { celoScanApiKey } = require('./.env.json') - -console.log(`Using truffle version for Solidity ${SOLC_VERSION}`) - -module.exports = { - plugins: ['truffle-plugin-verify'], - api_keys: { - celoscan: celoScanApiKey, - }, - compilers: { - solc: { - version: SOLC_VERSION, - settings: { - metadata: { useLiteralContent: true }, - evmVersion: 'istanbul', - }, - }, - }, - networks, -} - -if (process.argv.includes('--gas')) { - module.exports = { - compilers: { - solc: { - version: SOLC_VERSION, - settings: { - metadata: { useLiteralContent: true }, - evmVersion: 'istanbul', - }, - }, - }, - plugins: ['truffle-plugin-verify'], - api_keys: { - celoscan: celoScanApiKey, - }, - networks, - reporter: 'eth-gas-reporter', - reporterOptions: { - currency: 'USD', - }, - } -} diff --git a/packages/protocol/truffle-config0.8.js b/packages/protocol/truffle-config0.8.js deleted file mode 100644 index da81a714f..000000000 --- a/packages/protocol/truffle-config0.8.js +++ /dev/null @@ -1,45 +0,0 @@ -const SOLC_VERSION = '0.8.19' - -const parent = require('./truffle-config-parent.js') -const networks = { ...parent.networks } -const { celoScanApiKey } = require('./.env.json') - -console.log(`Using truffle version for Solidity ${SOLC_VERSION}`) - -module.exports = { - plugins: ['truffle-plugin-verify'], - api_keys: { - celoscan: celoScanApiKey, - }, - compilers: { - solc: { - version: SOLC_VERSION, - settings: { - metadata: { useLiteralContent: true }, - }, - }, - }, - networks, -} - -if (process.argv.includes('--gas')) { - module.exports = { - compilers: { - solc: { - version: SOLC_VERSION, - settings: { - metadata: { useLiteralContent: true }, - }, - }, - }, - plugins: ['truffle-plugin-verify'], - api_keys: { - celoscan: celoScanApiKey, - }, - networks, - reporter: 'eth-gas-reporter', - reporterOptions: { - currency: 'USD', - }, - } -} diff --git a/packages/protocol/tsconfig.json b/packages/protocol/tsconfig.json deleted file mode 100644 index 86ec49d29..000000000 --- a/packages/protocol/tsconfig.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "compileOnSave": false, - "compilerOptions": { - "allowSyntheticDefaultImports": true, - "esModuleInterop": true, - "baseUrl": ".", - "lib": [ - "es2015", - "es2016" - ], - "module": "commonjs", - "moduleResolution": "node", - "noUnusedLocals": true, - "noUnusedParameters": true, - "removeComments": false, - "skipLibCheck": true, - "sourceMap": true, - "target": "es5", - "downlevelIteration": true, - "resolveJsonModule": true - }, - "exclude": [ - "node_modules", - "wagmi.config.ts", - "abis" - ] -} \ No newline at end of file diff --git a/packages/protocol/tslint.json b/packages/protocol/tslint.json deleted file mode 100644 index 59a3611ad..000000000 --- a/packages/protocol/tslint.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "extends": ["@celo/typescript/tslint.json"], - "linterOptions": { - "include": ["**/*.ts"], - "exclude": ["types/contracts/*", "lib/**"] - }, - "rules": { - "no-implicit-dependencies": [ - true, - "dev", - [ - "contractPackages", - "@celo/protocol", - "types" - ] - ], - "no-global-arrow-functions": false, - "no-floating-promises": true, - "no-string-literal": false, - "ban": [ - true, - { "name": ["describe", "only"], "message": "don't focus tests" }, - { "name": ["it", "only"], "message": "don't focus tests" } - ] - } -} diff --git a/packages/protocol/twilio-config.enc b/packages/protocol/twilio-config.enc deleted file mode 100644 index 373cd390f..000000000 Binary files a/packages/protocol/twilio-config.enc and /dev/null differ diff --git a/packages/protocol/types/08.ts b/packages/protocol/types/08.ts deleted file mode 100644 index 8f06acdfa..000000000 --- a/packages/protocol/types/08.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './typechain-0.8'; diff --git a/packages/protocol/types/index.ts b/packages/protocol/types/index.ts deleted file mode 100644 index 013d0a55a..000000000 --- a/packages/protocol/types/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './typechain' diff --git a/packages/protocol/types/mento.ts b/packages/protocol/types/mento.ts deleted file mode 100644 index 85223b1b5..000000000 --- a/packages/protocol/types/mento.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './typechain-mento'; diff --git a/packages/protocol/wagmi.config.ts b/packages/protocol/wagmi.config.ts deleted file mode 100644 index 68b0a72c1..000000000 --- a/packages/protocol/wagmi.config.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { defineConfig } from '@wagmi/cli' -import { readFileSync } from 'fs' -import * as path from 'path' - -import { ABIS_BUILD_DIR, PublishContracts } from './scripts/consts' - -const contracts: { name: string; abi: any }[] = [] -for (const contractName of new Set(PublishContracts)) { - try { - const fileStr = readFileSync(path.join(ABIS_BUILD_DIR, `${contractName}.json`)) - contracts.push({ - name: contractName, - abi: JSON.parse(fileStr.toString()).abi, - }) - } catch (e) { - console.debug(`WARNING: ${contractName} artifact could not be fetched. Maybe it doesn't exist?`) - } -} - -export default defineConfig( - contracts.map(({ name, abi }) => ({ - out: path.join(ABIS_BUILD_DIR, `${name}.ts`), - contracts: [{ name, abi }], - plugins: [], - })) -) diff --git a/packages/sdk/base/src/package.test.ts b/packages/sdk/base/src/package.test.ts index 902f687a8..797ae0d65 100644 --- a/packages/sdk/base/src/package.test.ts +++ b/packages/sdk/base/src/package.test.ts @@ -1,13 +1,12 @@ -import { assert } from 'chai' import { readFileSync } from 'fs' -const pdef = JSON.parse(readFileSync('./package.json', 'utf-8')) +const packageJson = JSON.parse(readFileSync('./package.json', 'utf-8')) describe('Base package', () => { // @celo/base is built on the premise of having absolutely no dependencies, no exceptions made it('Should have an explicitly defined empty dependencies property', () => { - assert.isObject(pdef) - assert.property(pdef, 'dependencies') - assert.isEmpty(pdef.dependencies) + expect(packageJson).toBeInstanceOf(Object) + expect(packageJson).toHaveProperty('dependencies') + expect(packageJson.dependencies).toEqual({}) }) }) diff --git a/packages/sdk/contractkit/package.json b/packages/sdk/contractkit/package.json index 6e663d5af..4ddd07a39 100644 --- a/packages/sdk/contractkit/package.json +++ b/packages/sdk/contractkit/package.json @@ -43,7 +43,8 @@ "devDependencies": { "@celo/celo-devchain": "^6.0.3", "@celo/odis-identifiers": "^1.0.0", - "@celo/dev-utils": "0.0.1", + "@celo/dev-utils": "0.0.1-beta.1", + "@truffle/contract": "4.6.31", "@types/debug": "^4.1.5", "fetch-mock": "9.10.4", "ganache": "npm:@celo/ganache@7.8.0-unofficial.0", diff --git a/packages/sdk/network-utils/package.json b/packages/sdk/network-utils/package.json index e3a15d8b6..0e666a321 100644 --- a/packages/sdk/network-utils/package.json +++ b/packages/sdk/network-utils/package.json @@ -27,7 +27,7 @@ "debug": "^4.1.1" }, "devDependencies": { - "@celo/dev-utils": "0.0.1", + "@celo/dev-utils": "0.0.1-beta.1", "fetch-mock": "9.10.4" }, "engines": { diff --git a/packages/sdk/transactions-uri/package.json b/packages/sdk/transactions-uri/package.json index 7c72b089d..f6dee7308 100644 --- a/packages/sdk/transactions-uri/package.json +++ b/packages/sdk/transactions-uri/package.json @@ -32,7 +32,7 @@ }, "devDependencies": { "@celo/celo-devchain": "^6.0.3", - "@celo/dev-utils": "0.0.1", + "@celo/dev-utils": "0.0.1-beta.1", "@celo/contractkit": "^6.0.0", "dotenv": "^8.2.0" }, diff --git a/packages/sdk/wallets/wallet-rpc/package.json b/packages/sdk/wallets/wallet-rpc/package.json index 5988c46d9..c493b7980 100644 --- a/packages/sdk/wallets/wallet-rpc/package.json +++ b/packages/sdk/wallets/wallet-rpc/package.json @@ -32,7 +32,7 @@ "debug": "^4.1.1" }, "devDependencies": { - "@celo/dev-utils": "0.0.1", + "@celo/dev-utils": "0.0.1-beta.1", "@celo/contractkit": "^6.0.0", "bn.js": "^5.1.0", "web3": "1.10.0" diff --git a/patches/tslint+5.20.0.patch b/patches/tslint+5.20.0.patch deleted file mode 100644 index 106d41010..000000000 --- a/patches/tslint+5.20.0.patch +++ /dev/null @@ -1,12 +0,0 @@ -patch-package ---- a/node_modules/tslint/lib/linter.js -+++ b/node_modules/tslint/lib/linter.js -@@ -193,7 +193,7 @@ var Linter = /** @class */ (function () { - var oldSource = fs.readFileSync(filePath, "utf-8"); - fileNewSource = rule_1.Replacement.applyFixes(oldSource, fileFixes); - } -- fs.writeFileSync(filePath, fileNewSource); -+ fs.writeFileSync(path.resolve(filePath), fileNewSource); - _this.updateProgram(filePath); - }); - return source; diff --git a/remappings.txt b/remappings.txt deleted file mode 100644 index 5f9ae9dfb..000000000 --- a/remappings.txt +++ /dev/null @@ -1,6 +0,0 @@ -ds-test/=packages/protocol/lib/celo-foundry/lib/forge-std/lib/ds-test/src/ -forge-std/=packages/protocol/lib/celo-foundry/lib/forge-std/src/ -celo-foundry/=packages/protocol/lib/celo-foundry/src/ -openzeppelin-solidity/=packages/protocol/lib/openzeppelin-contracts/ -solidity-bytes-utils/=packages/protocol/lib/solidity-bytes-utils/ -contracts=packages/protocol/contracts/ diff --git a/scripts/check-packages.js b/scripts/check-packages.js deleted file mode 100644 index 2db200f0a..000000000 --- a/scripts/check-packages.js +++ /dev/null @@ -1,67 +0,0 @@ -const fs = require('fs') -const path = require('path') -const chalk = require('chalk') - -const FirebaseOrGAEProjects = ['faucet', 'web', 'notification-service'] - -// Set CWD to monorepo root -process.cwd(path.join(__dirname, '..')) - -const pkgJsonPath = (name) => path.join('./packages', name, 'package.json') -const readJSON = (path) => JSON.parse(fs.readFileSync(path)) -const readPkgJson = (name) => readJSON(pkgJsonPath(name)) - -const extractVersionNumber = (semverString) => { - if (semverString[0] == '~' || semverString[0] == '^') { - return semverString.slice(1) - } else { - return semverString - } -} - -const npmPackages = fs - .readdirSync('./packages') - .filter((name) => fs.existsSync(pkgJsonPath(name))) - .filter((name) => !FirebaseOrGAEProjects.includes(name)) -const pkgJsons = npmPackages.map((name) => readPkgJson(name)) -const versionMap = new Map(pkgJsons.map((p) => [p.name, p.version])) - -function getErrors(pkgJson) { - const interDependencies = [] - .concat( - Object.keys(pkgJson.dependencies || {}) - .filter((name) => versionMap.has(name)) - .map((name) => [name, pkgJson.dependencies[name]]) - ) - .concat( - Object.keys(pkgJson.devDependencies || {}) - .filter((name) => versionMap.has(name)) - .map((name) => [name, pkgJson.devDependencies[name]]) - ) - - const errors = [] - for ([name, versionString] of interDependencies) { - if (extractVersionNumber(versionString) != versionMap.get(name)) { - errors.push({ - from: pkgJson.name, - to: name, - expected: versionMap.get(name), - got: versionString, - }) - } - } - return errors -} - -const errors = [].concat(...pkgJsons.map(getErrors).filter((err) => err.length > 0)) - -console.log( - errors - .map( - (err) => - chalk`{red ${err.from}} => {red ${err.to}}. expected: {blue ${err.expected}} got: {green ${err.got}}` - ) - .join('\n') -) - -process.exit(errors.length > 0 ? 1 : 0) diff --git a/scripts/hooks/pre-push.js b/scripts/hooks/pre-push.js deleted file mode 100644 index 3451db8a9..000000000 --- a/scripts/hooks/pre-push.js +++ /dev/null @@ -1,98 +0,0 @@ -const { execSync } = require('child_process') -const chalk = require('chalk') -const path = require('path') -const exec = (args) => execSync(args).toString().trim() - -//////////////////////////////////////////////////////////////// -/// CONFIG -//////////////////////////////////////////////////////////////// - -// Set this to the FIRST day where commits are valid! -const THRESHOLD_DATE = new Date('2019-07-17') - -//////////////////////////////////////////////////////////////// -/// UTILITY FUNCTIONS -//////////////////////////////////////////////////////////////// - -function mergeBaseFor(refA, refB) { - return exec(`git merge-base ${refA} ${refB}`) -} - -function getCommitRange(change, remoteName) { - if (change.remoteSHA === '0000000000000000000000000000000000000000') { - // pushing a new branch - // => commit range = changes from master - const fromSHA = mergeBaseFor(`${remoteName}/master`, change.localSHA) - return [fromSHA, change.localSHA] - } else { - // push can be fast forward or not (push -f) - // so we get the common ancestor and commits from there - const fromSHA = mergeBaseFor(change.remoteSHA, change.localSHA) - // assuming a fast forward => fromSHA is remoteBranch current HEAD - return [fromSHA, change.remoteSHA, change.localSHA] - } -} - -/** Get the list for changed files between two commits */ -function getChangedFiled(fromSHA, toSHA) { - return exec(`git diff --name-only ${fromSHA}..${toSHA}`).split('\n') -} - -/** - * Get date from the first commit from all commits between - * to given commits - */ -function getDateFromFirstCommit(fromSHA, toSHA) { - const args = [ - 'log', - "--pretty='%cd'", // show only the commiterDate - '--date=short', // date in YYYY-MM-DD format - '--date-order', // order commits by date - '--reverse', // show olders commits first - `${fromSHA}..${toSHA}`, // show commits fromSHA to toSHA - ] - const dateStr = exec(`git ${args.join(' ')} | head -1`) - return new Date(dateStr) -} - -//////////////////////////////////////////////////////////////// -/// MAIN -//////////////////////////////////////////////////////////////// - -// must trim otherwise the name will be 'origin\n' - -const remoteName = execSync('git remote').toString().trim() -// create remote tracking branches to ensure we can compare current to origin/master -execSync('git ls-remote --heads origin master') - -execSync('git fetch origin') - -const changes = process.env.HUSKY_GIT_STDIN.split('\n') - .filter((line) => line !== '') - .map((line) => { - const [localRef, localSHA, remoteRef, remoteSHA] = line.split(' ') - return { localRef, localSHA, remoteRef, remoteSHA } - }) -for (const change of changes) { - const [from, to] = getCommitRange(change, remoteName) - - const changedFiles = getChangedFiled(from, to) - - const pushedMnemonicFiles = changedFiles.filter( - (name) => path.basename(name).startsWith('.env.mnemonic') && path.extname(name) !== '.enc' - ) - if (pushedMnemonicFiles.length > 0) { - console.error(`Trying to push conflicting files`) - console.log(`Conflicting Files:\n ${pushedMnemonicFiles.join('\n ')}`) - console.error(chalk.red(`(${change.remoteRef}) Push rejected!`)) - process.exit(1) - } - - const firstCommitDate = getDateFromFirstCommit(from, to) - if (firstCommitDate < THRESHOLD_DATE) { - console.error(`Trying to push a commit from a date older than ${THRESHOLD_DATE.toUTCString()}`) - console.error(`FirstCommitDate: ${firstCommitDate.toUTCString()}`) - console.error(chalk.red(`(${change.remoteRef}) Push rejected!`)) - process.exit(1) - } -} diff --git a/scripts/key_placer.sh b/scripts/key_placer.sh deleted file mode 100755 index d9460b2a1..000000000 --- a/scripts/key_placer.sh +++ /dev/null @@ -1,80 +0,0 @@ -#!/usr/bin/env bash - -echo "Processing encrypted files v2" - -# Set list of secret files to encrypt and decrypt. -files=( - ".env.mnemonic:celo-testnet" - ".env.mnemonic.alfajores:celo-testnet" - ".env.mnemonic.baklava:celo-testnet" - ".env.mnemonic.rc1:celo-testnet-production" -) - -if [[ -z "$1" ]]; then - echo "Encrypt or decrypt secret files using GCP keystore." - echo "usage: $0 < encrypt | decrypt >" - exit 1 -elif [[ $1 != "encrypt" ]] && [[ $1 != "decrypt" ]]; then - echo "invalid action $1. Choose 'encrypt' or 'decrypt'" - echo "usage: $0 < encrypt | decrypt >" - exit 1 -fi - -# this is to allow the script to be called from anywhere -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" -cd $DIR -cd .. - -# place templates to be used (if they exist) in case the environment -# doesn't have access to decryption keys -if [[ $1 == "decrypt" ]]; then - for file_path_map in "${files[@]}"; do - file_path=${file_path_map%%:*} - template_file_path="$file_path.template" - - if test -f "$template_file_path" && ! test -f "$file_path"; then - cp "$template_file_path" "$file_path" - fi - done -fi - -command -v gcloud > /dev/null 2>&1 -if [[ $? -eq 1 ]]; then - echo "gcloud is not installed - skipping ${1}ion" - exit 0 -fi - -for file_path_map in "${files[@]}"; do - file_path=${file_path_map%%:*} - environment=${file_path_map#*:} - encrypted_file_path="$file_path.enc" - - # When decrypting ensure the encrypted file exists or skip. - if [[ $1 == "decrypt" ]] && ! test -f "$encrypted_file_path"; then - echo "$encrypted_file_path does not exist, cannot decrypt - skipping file" >&2 - continue - fi - - # When encrypting ensure the plaintext file exists. - if [[ $1 == "encrypt" ]]; then - if [[ ! -f "$file_path" ]]; then - echo "$file_path does not exist, cannot encrypt - skipping file" >&2 - continue - fi - fi - - # Encrypt or decrypt this file. - gcloud kms $1 --ciphertext-file=$encrypted_file_path --plaintext-file=$file_path --key=github-mnemonic-key --keyring=celo-keyring --location=global --project $environment - if [[ $? -eq 1 ]]; then - echo "Only cLabs employees with $environment access can $1 keys - skipping ${1}ion" - exit 0 - fi -done - -if [[ $1 == "decrypt" ]]; then - echo "Encrypted files decrypted" -elif [[ $1 == "encrypt" ]]; then - echo "Decrypted files encrypted" -fi - -exit 0 diff --git a/yarn-audit-known-issues b/yarn-audit-known-issues deleted file mode 100644 index e69de29bb..000000000 diff --git a/yarn.lock b/yarn.lock index 0065c47e7..9574d0b75 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,281 +2,11 @@ # yarn lockfile v1 -"@0x/assert@^3.0.35", "@0x/assert@^3.0.36": - version "3.0.36" - resolved "https://registry.yarnpkg.com/@0x/assert/-/assert-3.0.36.tgz#91f82973e11826c08011a5830508246262b43284" - integrity sha512-sUtrV5MhixXvWZpATjFqIDtgvvv64duSTuOyPdPJjB+/Lcl5jQhlSNuoN0X3XP0P79Sp+6tuez5MupgFGPA2QQ== - dependencies: - "@0x/json-schemas" "^6.4.6" - "@0x/typescript-typings" "^5.3.2" - "@0x/utils" "^7.0.0" - "@types/node" "12.12.54" - lodash "^4.17.21" - valid-url "^1.0.9" - -"@0x/dev-utils@^5.0.3": - version "5.0.3" - resolved "https://registry.yarnpkg.com/@0x/dev-utils/-/dev-utils-5.0.3.tgz#8de9b2f8241caa649ceffc6b891122aa923150a0" - integrity sha512-V58tT2aiiHNSQtEt2XQWZDsPMsQ4wPDnjZRUaW38W46QasIFfCbcpKmfCsAGJyFxM7t0m0JJJwmYTJwZhCGcoQ== - dependencies: - "@0x/subproviders" "^8.0.1" - "@0x/types" "^3.3.7" - "@0x/typescript-typings" "^5.3.2" - "@0x/utils" "^7.0.0" - "@0x/web3-wrapper" "^8.0.1" - "@types/node" "12.12.54" - "@types/web3-provider-engine" "^14.0.0" - chai "^4.0.1" - chai-as-promised "^7.1.0" - chai-bignumber "^3.0.0" - dirty-chai "^2.0.1" - ethereum-types "^3.7.1" - lodash "^4.17.21" - web3-provider-engine "16.0.4" - -"@0x/json-schemas@^6.4.6": - version "6.4.6" - resolved "https://registry.yarnpkg.com/@0x/json-schemas/-/json-schemas-6.4.6.tgz#3904b8219ad2fefdf47ddb94fb65c1b9fb82d1d7" - integrity sha512-TaqvhOkmLN/vkcpMUNVFZBTnWP05ZVo9iGAnP1CG/B8l4rvnUbLZvWx8KeDKs62I/5d7jdYISvXyOwP4EwrG4w== - dependencies: - "@0x/typescript-typings" "^5.3.2" - "@types/node" "12.12.54" - ajv "^6.12.5" - lodash.values "^4.3.0" - -"@0x/sol-compiler@^4.8.3", "@0x/sol-compiler@^4.8.5": - version "4.8.5" - resolved "https://registry.yarnpkg.com/@0x/sol-compiler/-/sol-compiler-4.8.5.tgz#49579cee7de838d8ebd1bfd094a0d30a9e96506c" - integrity sha512-hAc3ZjpD+/fgSt/UQaAim8d2fQL3kWpnP5+tSEVf3/xetDDp3BhTOMi+wKnVuYo9FzuTgHx5MFueWM+mojE41A== - dependencies: - "@0x/assert" "^3.0.36" - "@0x/json-schemas" "^6.4.6" - "@0x/sol-resolver" "^3.1.13" - "@0x/types" "^3.3.7" - "@0x/typescript-typings" "^5.3.2" - "@0x/utils" "^7.0.0" - "@0x/web3-wrapper" "^8.0.1" - "@types/node" "12.12.54" - "@types/yargs" "^11.0.0" - chalk "^2.3.0" - chokidar "^3.0.2" - ethereum-types "^3.7.1" - ethereumjs-util "^7.1.5" - lodash "^4.17.21" - mkdirp "^0.5.1" - pluralize "^7.0.0" - require-from-string "^2.0.1" - semver "5.5.0" - solc "^0.8" - source-map-support "^0.5.0" - strip-comments "^2.0.1" - web3-eth-abi "^1.0.0-beta.24" - yargs "^17.5.1" - -"@0x/sol-coverage@^4.0.47": - version "4.0.49" - resolved "https://registry.yarnpkg.com/@0x/sol-coverage/-/sol-coverage-4.0.49.tgz#15bb1210263a7dacc5a19f939892a9fb15bf2e5a" - integrity sha512-gphKAO63NBysXgFV2fqxHmnBnHnD/i6rarmEwMKMKjWJ1shqQsKgJL984jBtek0UPsR5X4QM5tcHNKuCSe2Tuw== - dependencies: - "@0x/sol-tracing-utils" "^7.3.5" - "@0x/subproviders" "^8.0.1" - "@0x/typescript-typings" "^5.3.2" - "@types/minimatch" "^3.0.3" - "@types/node" "12.12.54" - ethereum-types "^3.7.1" - lodash "^4.17.21" - minimatch "^3.0.4" - web3-provider-engine "16.0.4" - -"@0x/sol-profiler@^4.1.37": - version "4.1.39" - resolved "https://registry.yarnpkg.com/@0x/sol-profiler/-/sol-profiler-4.1.39.tgz#2a2f13056d8306bdea242df1d2566c0d80ac5e1e" - integrity sha512-yrEHRun6RvXsg1NWhx4iH/YBeJXZDTQRAyNGQai+P1hrcOE7yoZ7PKtMv+69r3vCH38xVcWzF6xQKa7p4BIvlA== - dependencies: - "@0x/sol-tracing-utils" "^7.3.5" - "@0x/subproviders" "^8.0.1" - "@0x/typescript-typings" "^5.3.2" - "@0x/utils" "^7.0.0" - "@types/node" "12.12.54" - ethereum-types "^3.7.1" - ethereumjs-util "^7.1.5" - lodash "^4.17.21" - web3-provider-engine "16.0.4" - -"@0x/sol-resolver@^3.1.13": - version "3.1.13" - resolved "https://registry.yarnpkg.com/@0x/sol-resolver/-/sol-resolver-3.1.13.tgz#d985be51cec600384c4df101ad33956b844e3ed7" - integrity sha512-nQHqW7sOsDEH4ejH9nu60sCgFXEW08LM0v+5DimA/R7MizOW4LAG7OoHM+Oq8uPcHbeU0peFEDOW0idBsIzZ6g== - dependencies: - "@0x/types" "^3.3.7" - "@0x/typescript-typings" "^5.3.2" - "@types/node" "12.12.54" - lodash "^4.17.21" - -"@0x/sol-trace@^3.0.47": - version "3.0.49" - resolved "https://registry.yarnpkg.com/@0x/sol-trace/-/sol-trace-3.0.49.tgz#10b2a4e079c187a11d3fca9d32031c10fb3d0a7e" - integrity sha512-mCNbUCX6Oh1Z1e1g4AsD7sSbgMN7IGQyR0w+4xQYApgjwtYOaRPZMiluMXqp9nNHX75LwCfVd7NEIJIUMVQf2A== - dependencies: - "@0x/sol-tracing-utils" "^7.3.5" - "@0x/subproviders" "^8.0.1" - "@0x/typescript-typings" "^5.3.2" - "@types/node" "12.12.54" - chalk "^2.3.0" - ethereum-types "^3.7.1" - ethereumjs-util "^7.1.5" - lodash "^4.17.21" - loglevel "^1.6.1" - web3-provider-engine "16.0.4" - -"@0x/sol-tracing-utils@^7.3.5": - version "7.3.5" - resolved "https://registry.yarnpkg.com/@0x/sol-tracing-utils/-/sol-tracing-utils-7.3.5.tgz#9fe3fb36462424a72437a0310d872611bc5f970a" - integrity sha512-KzLTcUcLiQD5N/NzkZnIwI0i4w775z4w/H0o2FeM3Gp/0BcBx2DZ+sqKVoCEUSussm+jx2v8MNJnM3wcdvvDlg== - dependencies: - "@0x/dev-utils" "^5.0.3" - "@0x/sol-compiler" "^4.8.5" - "@0x/sol-resolver" "^3.1.13" - "@0x/subproviders" "^8.0.1" - "@0x/typescript-typings" "^5.3.2" - "@0x/utils" "^7.0.0" - "@0x/web3-wrapper" "^8.0.1" - "@types/node" "12.12.54" - "@types/solidity-parser-antlr" "^0.2.3" - chalk "^2.3.0" - ethereum-types "^3.7.1" - ethereumjs-util "^7.1.5" - ethers "~4.0.4" - glob "^7.1.2" - istanbul "^0.4.5" - lodash "^4.17.21" - loglevel "^1.6.1" - mkdirp "^0.5.1" - rimraf "^2.6.2" - semaphore-async-await "^1.5.1" - solc "^0.8" - solidity-parser-antlr "^0.4.2" - -"@0x/subproviders@^7.0.1": - version "7.0.1" - resolved "https://registry.yarnpkg.com/@0x/subproviders/-/subproviders-7.0.1.tgz#3e74cbe61ae746bea67766821f226398978a0cc0" - integrity sha512-S5LrUg12szE8T3U+2ymcdiH4zOkSyGJIh3FRN9jXspwQCe6+fggEymt6n0SyK3p1QiHipVkCxhjTR/53+shwsg== - dependencies: - "@0x/assert" "^3.0.35" - "@0x/types" "^3.3.7" - "@0x/typescript-typings" "^5.3.2" - "@0x/utils" "^7.0.0" - "@0x/web3-wrapper" "^8.0.0" - "@ethereumjs/common" "^2.6.3" - "@ethereumjs/tx" "^3.5.1" - "@ledgerhq/hw-app-eth" "^5.53.0" - "@ledgerhq/hw-transport-webusb" "^5.53.1" - "@types/hdkey" "^0.7.0" - "@types/node" "12.12.54" - "@types/web3-provider-engine" "^14.0.0" - bip39 "^2.5.0" - bn.js "^4.11.8" - ethereum-types "^3.7.1" - ethereumjs-util "^7.1.5" - ganache "^7.4.0" - hdkey "^0.7.1" - json-rpc-error "2.0.0" - lodash "^4.17.21" - semaphore-async-await "^1.5.1" - web3-provider-engine "16.0.4" - optionalDependencies: - "@ledgerhq/hw-transport-node-hid" "^5.51.1" - -"@0x/subproviders@^8.0.1": - version "8.0.1" - resolved "https://registry.yarnpkg.com/@0x/subproviders/-/subproviders-8.0.1.tgz#b934547bfa1c8049030b243a134de9755792d53a" - integrity sha512-Lax7Msb1Ef9D6Dd7PQ19oPgjl5GIrKje7XsrO7YCfx5A0RM3Hr4nSQIxgg78jwvuulSFxQ5Sr8WiZ2hTHATtQg== - dependencies: - "@0x/assert" "^3.0.36" - "@0x/types" "^3.3.7" - "@0x/typescript-typings" "^5.3.2" - "@0x/utils" "^7.0.0" - "@0x/web3-wrapper" "^8.0.1" - "@ethereumjs/common" "^2.6.3" - "@ethereumjs/tx" "^3.5.1" - "@types/hdkey" "^0.7.0" - "@types/node" "12.12.54" - "@types/web3-provider-engine" "^14.0.0" - bip39 "2.5.0" - ethereum-types "^3.7.1" - ethereumjs-util "^7.1.5" - ganache "^7.4.0" - hdkey "2.1.0" - json-rpc-error "2.0.0" - lodash "^4.17.21" - web3-provider-engine "16.0.4" - -"@0x/types@^3.3.7": - version "3.3.7" - resolved "https://registry.yarnpkg.com/@0x/types/-/types-3.3.7.tgz#2a8556b3398b6d6fac942c63de23ab22836624ee" - integrity sha512-6lPXPnvKaIfAJ5hIgs81SytqNCPCLstQ/DA598iLpb90KKjjz8QsdrfII4JeKdrEREvLcWSH9SeH4sNPWyLhlA== - dependencies: - "@types/node" "12.12.54" - bignumber.js "~9.0.2" - ethereum-types "^3.7.1" - -"@0x/typescript-typings@^5.3.2": - version "5.3.2" - resolved "https://registry.yarnpkg.com/@0x/typescript-typings/-/typescript-typings-5.3.2.tgz#b2b2a46ebff7f9d885b1357feae615225cb0bb31" - integrity sha512-VIo8PS/IRXrI1aEzM8TenUMViX4MFMKBnIAwqC4K/ewVDSnKyYZSk8fzw0XZph6tN07obchPf+1sHIWYe8EUow== - dependencies: - "@types/bn.js" "^4.11.0" - "@types/node" "12.12.54" - "@types/react" "*" - bignumber.js "~9.0.2" - ethereum-types "^3.7.1" - popper.js "1.14.3" - -"@0x/utils@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@0x/utils/-/utils-7.0.0.tgz#322168b21cf11741003c9cc490b13adafbe57393" - integrity sha512-g+Bp0eHUGhnVGeVZqGn7UVtpzs/FuoXksiDaajfJrHFW0owwo5YwpwFIAVU7/ca0B6IKa74e71gskLwWGINEFg== - dependencies: - "@0x/types" "^3.3.7" - "@0x/typescript-typings" "^5.3.2" - "@types/mocha" "^5.2.7" - "@types/node" "12.12.54" - abortcontroller-polyfill "^1.1.9" - bignumber.js "~9.0.2" - chalk "^2.3.0" - detect-node "2.0.3" - ethereum-types "^3.7.1" - ethereumjs-util "^7.1.5" - ethers "~4.0.4" - isomorphic-fetch "^3.0.0" - js-sha3 "^0.7.0" - lodash "^4.17.21" - -"@0x/web3-wrapper@^8.0.0", "@0x/web3-wrapper@^8.0.1": - version "8.0.1" - resolved "https://registry.yarnpkg.com/@0x/web3-wrapper/-/web3-wrapper-8.0.1.tgz#3625e63737d005fe6a92b71d0e676b4d03e88c60" - integrity sha512-2rqugeCld5r/3yg+Un9sPCUNVeZW5J64Fm6i/W6qRE87X+spIJG48oJymTjSMDXw/w3FaP4nAvhSj2C5fvhN6w== - dependencies: - "@0x/assert" "^3.0.36" - "@0x/json-schemas" "^6.4.6" - "@0x/typescript-typings" "^5.3.2" - "@0x/utils" "^7.0.0" - "@types/node" "12.12.54" - ethereum-types "^3.7.1" - ethereumjs-util "^7.1.5" - ethers "~4.0.4" - lodash "^4.17.21" - "@adraffy/ens-normalize@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.9.0.tgz#223572538f6bea336750039bb43a4016dcc8182d" integrity sha512-iowxq3U30sghZotgl4s/oJRci6WPBfNO5YYgk2cIOMCHr3LeGPcsZjCEr+33Q4N+oV3OABDAtA+pyvWjbvBifQ== -"@adraffy/ens-normalize@1.9.4": - version "1.9.4" - resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.9.4.tgz#aae21cb858bbb0411949d5b7b3051f4209043f62" - integrity sha512-UK0bHA7hh9cR39V+4gl2/NnBBjoXIxkuWAPCaY4X7fbH4L/azIi7ilWOCjMUYfpJgraLUAqkRi2BqrjME8Rynw== - "@ampproject/remapping@^2.2.0": version "2.2.1" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" @@ -285,114 +15,6 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" -"@apollo/protobufjs@1.2.6": - version "1.2.6" - resolved "https://registry.yarnpkg.com/@apollo/protobufjs/-/protobufjs-1.2.6.tgz#d601e65211e06ae1432bf5993a1a0105f2862f27" - integrity sha512-Wqo1oSHNUj/jxmsVp4iR3I480p6qdqHikn38lKrFhfzcDJ7lwd7Ck7cHRl4JE81tWNArl77xhnG/OkZhxKBYOw== - 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/long" "^4.0.0" - "@types/node" "^10.1.0" - long "^4.0.0" - -"@apollo/protobufjs@1.2.7": - version "1.2.7" - resolved "https://registry.yarnpkg.com/@apollo/protobufjs/-/protobufjs-1.2.7.tgz#3a8675512817e4a046a897e5f4f16415f16a7d8a" - integrity sha512-Lahx5zntHPZia35myYDBRuF58tlwPskwHc5CWBZC/4bMKB6siTBWwtMrkqXcsNwQiFSzSx5hKdRPUmemrEp3Gg== - 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/long" "^4.0.0" - long "^4.0.0" - -"@apollo/usage-reporting-protobuf@^4.0.0": - version "4.1.0" - resolved "https://registry.yarnpkg.com/@apollo/usage-reporting-protobuf/-/usage-reporting-protobuf-4.1.0.tgz#b54b8c32702bbe81aa0e399076ddabaf75a13f9b" - integrity sha512-hXouMuw5pQVkzi8dgMybmr6Y11+eRmMQVoB5TF0HyTwAg9SOq/v3OCuiYqcVUKdBcskU9Msp+XvjAk0GKpWCwQ== - dependencies: - "@apollo/protobufjs" "1.2.7" - -"@apollo/utils.dropunuseddefinitions@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@apollo/utils.dropunuseddefinitions/-/utils.dropunuseddefinitions-1.1.0.tgz#02b04006442eaf037f4c4624146b12775d70d929" - integrity sha512-jU1XjMr6ec9pPoL+BFWzEPW7VHHulVdGKMkPAMiCigpVIT11VmCbnij0bWob8uS3ODJ65tZLYKAh/55vLw2rbg== - -"@apollo/utils.keyvaluecache@^1.0.1": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@apollo/utils.keyvaluecache/-/utils.keyvaluecache-1.0.2.tgz#2bfe358c4d82f3a0950518451996758c52613f57" - integrity sha512-p7PVdLPMnPzmXSQVEsy27cYEjVON+SH/Wb7COyW3rQN8+wJgT1nv9jZouYtztWW8ZgTkii5T6tC9qfoDREd4mg== - dependencies: - "@apollo/utils.logger" "^1.0.0" - lru-cache "7.10.1 - 7.13.1" - -"@apollo/utils.logger@^1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@apollo/utils.logger/-/utils.logger-1.0.1.tgz#aea0d1bb7ceb237f506c6bbf38f10a555b99a695" - integrity sha512-XdlzoY7fYNK4OIcvMD2G94RoFZbzTQaNP0jozmqqMudmaGo2I/2Jx71xlDJ801mWA/mbYRihyaw6KJii7k5RVA== - -"@apollo/utils.printwithreducedwhitespace@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@apollo/utils.printwithreducedwhitespace/-/utils.printwithreducedwhitespace-1.1.0.tgz#c466299a4766eef8577a2a64c8f27712e8bd7e30" - integrity sha512-GfFSkAv3n1toDZ4V6u2d7L4xMwLA+lv+6hqXicMN9KELSJ9yy9RzuEXaX73c/Ry+GzRsBy/fdSUGayGqdHfT2Q== - -"@apollo/utils.removealiases@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@apollo/utils.removealiases/-/utils.removealiases-1.0.0.tgz#75f6d83098af1fcae2d3beb4f515ad4a8452a8c1" - integrity sha512-6cM8sEOJW2LaGjL/0vHV0GtRaSekrPQR4DiywaApQlL9EdROASZU5PsQibe2MWeZCOhNrPRuHh4wDMwPsWTn8A== - -"@apollo/utils.sortast@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@apollo/utils.sortast/-/utils.sortast-1.1.0.tgz#93218c7008daf3e2a0725196085a33f5aab5ad07" - integrity sha512-VPlTsmUnOwzPK5yGZENN069y6uUHgeiSlpEhRnLFYwYNoJHsuJq2vXVwIaSmts015WTPa2fpz1inkLYByeuRQA== - dependencies: - lodash.sortby "^4.7.0" - -"@apollo/utils.stripsensitiveliterals@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@apollo/utils.stripsensitiveliterals/-/utils.stripsensitiveliterals-1.2.0.tgz#4920651f36beee8e260e12031a0c5863ad0c7b28" - integrity sha512-E41rDUzkz/cdikM5147d8nfCFVKovXxKBcjvLEQ7bjZm/cg9zEcXvS6vFY8ugTubI3fn6zoqo0CyU8zT+BGP9w== - -"@apollo/utils.usagereporting@^1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@apollo/utils.usagereporting/-/utils.usagereporting-1.0.1.tgz#3c70b49e554771659576fe35381c7a4b321d27fd" - integrity sha512-6dk+0hZlnDbahDBB2mP/PZ5ybrtCJdLMbeNJD+TJpKyZmSY6bA3SjI8Cr2EM9QA+AdziywuWg+SgbWUF3/zQqQ== - dependencies: - "@apollo/usage-reporting-protobuf" "^4.0.0" - "@apollo/utils.dropunuseddefinitions" "^1.1.0" - "@apollo/utils.printwithreducedwhitespace" "^1.1.0" - "@apollo/utils.removealiases" "1.0.0" - "@apollo/utils.sortast" "^1.1.0" - "@apollo/utils.stripsensitiveliterals" "^1.2.0" - -"@apollographql/apollo-tools@^0.5.3": - version "0.5.4" - resolved "https://registry.yarnpkg.com/@apollographql/apollo-tools/-/apollo-tools-0.5.4.tgz#cb3998c6cf12e494b90c733f44dd9935e2d8196c" - integrity sha512-shM3q7rUbNyXVVRkQJQseXv6bnYM3BUma/eZhwXR4xsuM+bqWnJKvW7SAfRjP7LuSCocrexa5AXhjjawNHrIlw== - -"@apollographql/graphql-playground-html@1.6.29": - version "1.6.29" - resolved "https://registry.yarnpkg.com/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.29.tgz#a7a646614a255f62e10dcf64a7f68ead41dec453" - integrity sha512-xCcXpoz52rI4ksJSdOCxeOCn2DLocxwHf9dVT/Q90Pte1LX+LY+91SFtJF3KXVHH8kEin+g1KKCQPKBjZJfWNA== - dependencies: - xss "^1.0.8" - "@azure/abort-controller@^1.0.0", "@azure/abort-controller@^1.0.4": version "1.1.0" resolved "https://registry.yarnpkg.com/@azure/abort-controller/-/abort-controller-1.1.0.tgz#788ee78457a55af8a1ad342acb182383d2119249" @@ -582,7 +204,7 @@ "@babel/highlight" "^7.22.13" chalk "^2.4.2" -"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.21.4": +"@babel/compat-data@^7.21.4": version "7.21.4" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.21.4.tgz#457ffe647c480dff59c2be092fc3acf71195c87f" integrity sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g== @@ -628,7 +250,7 @@ "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" -"@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.21.4": +"@babel/helper-compilation-targets@^7.21.4": version "7.21.4" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.4.tgz#770cd1ce0889097ceacb99418ee6934ef0572656" integrity sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg== @@ -639,18 +261,6 @@ lru-cache "^5.1.1" semver "^6.3.0" -"@babel/helper-define-polyfill-provider@^0.3.3": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz#8612e55be5d51f0cd1f36b4a5a83924e89884b7a" - integrity sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww== - dependencies: - "@babel/helper-compilation-targets" "^7.17.7" - "@babel/helper-plugin-utils" "^7.16.7" - debug "^4.1.1" - lodash.debounce "^4.0.8" - resolve "^1.14.2" - semver "^6.1.2" - "@babel/helper-environment-visitor@^7.18.9": version "7.18.9" resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" @@ -676,7 +286,7 @@ dependencies: "@babel/types" "^7.22.5" -"@babel/helper-module-imports@^7.18.6", "@babel/helper-module-imports@^7.21.4": +"@babel/helper-module-imports@^7.18.6": version "7.21.4" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz#ac88b2f76093637489e718a90cec6cf8a9b029af" integrity sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg== @@ -697,7 +307,7 @@ "@babel/traverse" "^7.21.2" "@babel/types" "^7.21.2" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.8.0": +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.8.0": version "7.20.2" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz#d1b9000752b18d0877cff85a5c376ce5c3121629" integrity sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ== @@ -883,19 +493,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.20.2" -"@babel/plugin-transform-runtime@^7.5.5": - version "7.21.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.21.4.tgz#2e1da21ca597a7d01fc96b699b21d8d2023191aa" - integrity sha512-1J4dhrw1h1PqnNNpzwxQ2UBymJUF8KuPjAAnlLwZcGhHAIqUigFW7cdK6GHoB64ubY4qXQNYknoUeks4Wz7CUA== - dependencies: - "@babel/helper-module-imports" "^7.21.4" - "@babel/helper-plugin-utils" "^7.20.2" - babel-plugin-polyfill-corejs2 "^0.3.3" - babel-plugin-polyfill-corejs3 "^0.6.0" - babel-plugin-polyfill-regenerator "^0.4.1" - semver "^6.3.0" - -"@babel/runtime@^7.0.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.15.4", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.5.5": version "7.21.0" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.0.tgz#5b55c9d394e5fcf304909a8b00c07dc217b56673" integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw== @@ -909,12 +507,12 @@ dependencies: regenerator-runtime "^0.14.0" -"@babel/runtime@^7.6.3", "@babel/runtime@^7.9.2": - version "7.21.5" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.5.tgz#8492dddda9644ae3bda3b45eabe87382caee7200" - integrity sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q== +"@babel/runtime@^7.4.4": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.6.tgz#c05e610dc228855dc92ef1b53d07389ed8ab521d" + integrity sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ== dependencies: - regenerator-runtime "^0.13.11" + regenerator-runtime "^0.14.0" "@babel/template@^7.20.7", "@babel/template@^7.3.3": version "7.20.7" @@ -1022,6 +620,19 @@ web3 "1.10.0" web3-core-helpers "1.10.0" +"@celo/dev-utils@0.0.1-beta.1": + version "0.0.1-beta.1" + resolved "https://registry.yarnpkg.com/@celo/dev-utils/-/dev-utils-0.0.1-beta.1.tgz#f147952d03fec73cfb1ebfa4211234aba4f9ce60" + integrity sha512-VnRXfoyz5SlXPc7Xjj5VCIeY8OlbPKeJzu/gjNseX/gFBOorZ3bPFqM0VsH2Pv4EHaXx33bwv7XAIzp5iaIWKA== + dependencies: + bignumber.js "^9.0.0" + fs-extra "^8.1.0" + ganache "npm:@celo/ganache@7.8.0-unofficial.0" + targz "^1.0.1" + tmp "^0.1.0" + web3 "1.10.0" + web3-core-helpers "1.10.0" + "@celo/identity@^5.1.1": version "5.1.1" resolved "https://registry.yarnpkg.com/@celo/identity/-/identity-5.1.1.tgz#e56cea67d820c7deae147e50b353f3c76b3e6d4d" @@ -1075,13 +686,6 @@ is-base64 "^1.1.0" node-fetch "^2.6.9" -"@celo/typechain-target-web3-v1-celo@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@celo/typechain-target-web3-v1-celo/-/typechain-target-web3-v1-celo-1.0.0.tgz#9b22ae2624c06d9cddb1616fa232970b45056aa9" - integrity sha512-x73qZsvMyzPnMnV2aTyGfCKI5/Se0PE7JUgzcCx/qn8iq2kywIOQoJweokWqZu9f6RpEvrzcjTEB1upJOBguuQ== - dependencies: - typechain "^4.0.3" - "@chainsafe/as-sha256@^0.3.1": version "0.3.1" resolved "https://registry.yarnpkg.com/@chainsafe/as-sha256/-/as-sha256-0.3.1.tgz#3639df0e1435cab03f4d9870cc3ac079e57a6fc9" @@ -1353,148 +957,6 @@ resolved "https://registry.yarnpkg.com/@ensdomains/resolver/-/resolver-0.2.4.tgz#c10fe28bf5efbf49bff4666d909aed0265efbc89" integrity sha512-bvaTH34PMCbv6anRa9I/0zjLJgY4EuznbEMgbV77JBCQ9KNC46rzi0avuxpOfu+xDjPEtSFGqVEOr5GlUSGudA== -"@esbuild/android-arm64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.16.17.tgz#cf91e86df127aa3d141744edafcba0abdc577d23" - integrity sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg== - -"@esbuild/android-arm@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.16.17.tgz#025b6246d3f68b7bbaa97069144fb5fb70f2fff2" - integrity sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw== - -"@esbuild/android-x64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.16.17.tgz#c820e0fef982f99a85c4b8bfdd582835f04cd96e" - integrity sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ== - -"@esbuild/darwin-arm64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.16.17.tgz#edef4487af6b21afabba7be5132c26d22379b220" - integrity sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w== - -"@esbuild/darwin-x64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.16.17.tgz#42829168730071c41ef0d028d8319eea0e2904b4" - integrity sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg== - -"@esbuild/freebsd-arm64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.17.tgz#1f4af488bfc7e9ced04207034d398e793b570a27" - integrity sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw== - -"@esbuild/freebsd-x64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.16.17.tgz#636306f19e9bc981e06aa1d777302dad8fddaf72" - integrity sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug== - -"@esbuild/linux-arm64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.16.17.tgz#a003f7ff237c501e095d4f3a09e58fc7b25a4aca" - integrity sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g== - -"@esbuild/linux-arm@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.16.17.tgz#b591e6a59d9c4fe0eeadd4874b157ab78cf5f196" - integrity sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ== - -"@esbuild/linux-ia32@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.16.17.tgz#24333a11027ef46a18f57019450a5188918e2a54" - integrity sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg== - -"@esbuild/linux-loong64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.16.17.tgz#d5ad459d41ed42bbd4d005256b31882ec52227d8" - integrity sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ== - -"@esbuild/linux-mips64el@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.16.17.tgz#4e5967a665c38360b0a8205594377d4dcf9c3726" - integrity sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw== - -"@esbuild/linux-ppc64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.16.17.tgz#206443a02eb568f9fdf0b438fbd47d26e735afc8" - integrity sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g== - -"@esbuild/linux-riscv64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.16.17.tgz#c351e433d009bf256e798ad048152c8d76da2fc9" - integrity sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw== - -"@esbuild/linux-s390x@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.16.17.tgz#661f271e5d59615b84b6801d1c2123ad13d9bd87" - integrity sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w== - -"@esbuild/linux-x64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.16.17.tgz#e4ba18e8b149a89c982351443a377c723762b85f" - integrity sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw== - -"@esbuild/netbsd-x64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.16.17.tgz#7d4f4041e30c5c07dd24ffa295c73f06038ec775" - integrity sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA== - -"@esbuild/openbsd-x64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.16.17.tgz#970fa7f8470681f3e6b1db0cc421a4af8060ec35" - integrity sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg== - -"@esbuild/sunos-x64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.16.17.tgz#abc60e7c4abf8b89fb7a4fe69a1484132238022c" - integrity sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw== - -"@esbuild/win32-arm64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.16.17.tgz#7b0ff9e8c3265537a7a7b1fd9a24e7bd39fcd87a" - integrity sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw== - -"@esbuild/win32-ia32@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.16.17.tgz#e90fe5267d71a7b7567afdc403dfd198c292eb09" - integrity sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig== - -"@esbuild/win32-x64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.16.17.tgz#c5a1a4bfe1b57f0c3e61b29883525c6da3e5c091" - integrity sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q== - -"@ethereumjs/block@4.2.1", "@ethereumjs/block@^4.2.1": - version "4.2.1" - resolved "https://registry.yarnpkg.com/@ethereumjs/block/-/block-4.2.1.tgz#cb0d8b770fe69c61e6e41d6693d285de76b3a7cb" - integrity sha512-Z/Ty8EkD8o5tvEX5JPrr0pvf60JkSxmwV231aBZ744N75SLvq54dTu/Gk7azC/2xaWhSu1dOp5D5+bryqgG5Cg== - dependencies: - "@ethereumjs/common" "^3.1.1" - "@ethereumjs/rlp" "^4.0.1" - "@ethereumjs/trie" "^5.0.4" - "@ethereumjs/tx" "^4.1.1" - "@ethereumjs/util" "^8.0.5" - ethereum-cryptography "^1.1.2" - ethers "^5.7.1" - -"@ethereumjs/blockchain@6.2.1": - version "6.2.1" - resolved "https://registry.yarnpkg.com/@ethereumjs/blockchain/-/blockchain-6.2.1.tgz#9bda6b26dff7399a8f6f71efa86ae6dfe343f916" - integrity sha512-gP7EtXAPMDna/e28ZMDErfatF/2FRYi4HA2qleIKuEC33RbizGmTK34BoEuSXVeWHTIyNBLO5m9fwQhsF2LNyA== - dependencies: - "@ethereumjs/block" "^4.2.1" - "@ethereumjs/common" "^3.1.1" - "@ethereumjs/ethash" "^2.0.4" - "@ethereumjs/rlp" "^4.0.1" - "@ethereumjs/trie" "^5.0.4" - "@ethereumjs/tx" "^4.1.1" - "@ethereumjs/util" "^8.0.5" - abstract-level "^1.0.3" - debug "^4.3.3" - ethereum-cryptography "^1.1.2" - level "^8.0.0" - lru-cache "^5.1.1" - memory-level "^1.0.0" - "@ethereumjs/common@2.5.0": version "2.5.0" resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.5.0.tgz#ec61551b31bef7a69d1dc634d8932468866a4268" @@ -1503,15 +965,7 @@ crc-32 "^1.2.0" ethereumjs-util "^7.1.1" -"@ethereumjs/common@3.1.1", "@ethereumjs/common@^3.1.1": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-3.1.1.tgz#6f754c8933727ad781f63ca3929caab542fe184e" - integrity sha512-iEl4gQtcrj2udNhEizs04z7WA15ez1QoXL0XzaCyaNgwRyXezIg1DnfNeZUUpJnkrOF/0rYXyq2UFSLxt1NPQg== - dependencies: - "@ethereumjs/util" "^8.0.5" - crc-32 "^1.2.0" - -"@ethereumjs/common@^2.5.0", "@ethereumjs/common@^2.6.3", "@ethereumjs/common@^2.6.4": +"@ethereumjs/common@^2.5.0": version "2.6.5" resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.5.tgz#0a75a22a046272579d91919cb12d84f2756e8d30" integrity sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA== @@ -1519,33 +973,7 @@ crc-32 "^1.2.0" ethereumjs-util "^7.1.5" -"@ethereumjs/ethash@^2.0.4": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@ethereumjs/ethash/-/ethash-2.0.4.tgz#1892e8e17a11b10efeee3075fb09cd3cbd12c33b" - integrity sha512-WREZZEZKh8baGbG4IwLXvjA+ItFWzD/myUnefKALuAcB9+um93e1YBaeSQzeyY6m5jiDmpxu55SxF0mB8e+xdQ== - dependencies: - "@ethereumjs/block" "^4.2.1" - "@ethereumjs/rlp" "^4.0.1" - "@ethereumjs/util" "^8.0.5" - abstract-level "^1.0.3" - bigint-crypto-utils "^3.0.23" - ethereum-cryptography "^1.1.2" - -"@ethereumjs/evm@npm:@celo/ethereumjs-evm@1.3.1-unofficial.0": - version "1.3.1-unofficial.0" - resolved "https://registry.yarnpkg.com/@celo/ethereumjs-evm/-/ethereumjs-evm-1.3.1-unofficial.0.tgz#9083573f0fbf3d45a3ed3d69af8c78509e86803c" - integrity sha512-N321IctdVHY6PHesKGnUitjQ0dTRUBggordAmuBRF58foUwW5gMVzAY8c6L7rZVHiuiLYIvxQuQf8iadVzO5TA== - dependencies: - "@ethereumjs/common" "3.1.1" - "@ethereumjs/tx" "4.1.1" - "@ethereumjs/util" "8.0.5" - "@ethersproject/providers" "^5.7.1" - debug "^4.3.3" - ethereum-cryptography "^1.1.2" - mcl-wasm "^0.7.1" - rustbn.js "~0.2.0" - -"@ethereumjs/rlp@4.0.1", "@ethereumjs/rlp@^4.0.0-beta.2", "@ethereumjs/rlp@^4.0.1": +"@ethereumjs/rlp@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@ethereumjs/rlp/-/rlp-4.0.1.tgz#626fabfd9081baab3d0a3074b0c7ecaf674aaa41" integrity sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw== @@ -1555,29 +983,6 @@ resolved "https://registry.yarnpkg.com/@ethereumjs/rlp/-/rlp-5.0.0.tgz#dd81b32b2237bc32fb1b54534f8ff246a6c89d9b" integrity sha512-WuS1l7GJmB0n0HsXLozCoEFc9IwYgf3l0gCkKVYgR67puVF1O4OpEaN0hWmm1c+iHUHFCKt1hJrvy5toLg+6ag== -"@ethereumjs/statemanager@1.0.4": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@ethereumjs/statemanager/-/statemanager-1.0.4.tgz#02fb3f05794a2476a78d73660745e9815b476e02" - integrity sha512-+dNZGqOUXlA+ifkSlz6AvEF/PCRZD7vqKcruoyGtaxOQ0gdfvL/lDiuzV07fECjrqPAEDnQwcO4CTGv+On/0wA== - dependencies: - "@ethereumjs/common" "^3.1.1" - "@ethereumjs/rlp" "^4.0.1" - debug "^4.3.3" - ethereum-cryptography "^1.1.2" - ethers "^5.7.1" - js-sdsl "^4.1.4" - -"@ethereumjs/trie@5.0.4", "@ethereumjs/trie@^5.0.4": - version "5.0.4" - resolved "https://registry.yarnpkg.com/@ethereumjs/trie/-/trie-5.0.4.tgz#eb06ce2c7957f6a8f07c0db43fb0335b256f3705" - integrity sha512-ycYtAF7BJAu9eaCtrEX+efE5xEQEfItRXXHBcTSMHsF7NfLHcniI0S7KUVYXbJ6imczBmnMHeggCqv8PYQbbOw== - dependencies: - "@ethereumjs/rlp" "^4.0.1" - "@ethereumjs/util" "^8.0.5" - "@types/readable-stream" "^2.3.13" - ethereum-cryptography "^1.1.2" - readable-stream "^3.6.0" - "@ethereumjs/tx@3.3.2": version "3.3.2" resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.3.2.tgz#348d4624bf248aaab6c44fec2ae67265efe3db00" @@ -1586,36 +991,7 @@ "@ethereumjs/common" "^2.5.0" ethereumjs-util "^7.1.2" -"@ethereumjs/tx@4.1.1", "@ethereumjs/tx@^4.1.1": - version "4.1.1" - resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-4.1.1.tgz#d1b5bf2c4fd3618f2f333b66e262848530d4686a" - integrity sha512-QDj7nuROfoeyK83RObMA0XCZ+LUDdneNkSCIekO498uEKTY25FxI4Whduc/6j0wdd4IqpQvkq+/7vxSULjGIBQ== - dependencies: - "@chainsafe/ssz" "0.9.4" - "@ethereumjs/common" "^3.1.1" - "@ethereumjs/rlp" "^4.0.1" - "@ethereumjs/util" "^8.0.5" - "@ethersproject/providers" "^5.7.2" - ethereum-cryptography "^1.1.2" - -"@ethereumjs/tx@^3.3.0", "@ethereumjs/tx@^3.5.1": - version "3.5.2" - resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.5.2.tgz#197b9b6299582ad84f9527ca961466fce2296c1c" - integrity sha512-gQDNJWKrSDGu2w7w0PzVXVBNMzb7wwdDOmOqczmhNjqFxFuIbhVJDwiGEnxFNC2/b8ifcZzY7MLcluizohRzNw== - dependencies: - "@ethereumjs/common" "^2.6.4" - ethereumjs-util "^7.1.5" - -"@ethereumjs/util@8.0.2": - version "8.0.2" - resolved "https://registry.yarnpkg.com/@ethereumjs/util/-/util-8.0.2.tgz#b7348fc7253649b0f00685a94546c6eee1fad819" - integrity sha512-b1Fcxmq+ckCdoLPhVIBkTcH8szigMapPuEmD8EDakvtI5Na5rzmX1sBW73YQqaPc7iUxGCAzZP1LrFQ7aEMugA== - dependencies: - "@ethereumjs/rlp" "^4.0.0-beta.2" - async "^3.2.4" - ethereum-cryptography "^1.1.2" - -"@ethereumjs/util@8.0.5", "@ethereumjs/util@^8.0.5": +"@ethereumjs/util@8.0.5": version "8.0.5" resolved "https://registry.yarnpkg.com/@ethereumjs/util/-/util-8.0.5.tgz#b9088fc687cc13f0c1243d6133d145dfcf3fe446" integrity sha512-259rXKK3b3D8HRVdRmlOEi6QFvwxdt304hhrEAmpZhsj7ufXEOTIc9JRZPMnXatKjECokdLNBcDOFBeBSzAIaw== @@ -1633,26 +1009,7 @@ ethereum-cryptography "^2.0.0" micro-ftch "^0.3.1" -"@ethereumjs/vm@npm:@celo/ethereumjs-vm@6.4.1-unofficial.0": - version "6.4.1-unofficial.0" - resolved "https://registry.yarnpkg.com/@celo/ethereumjs-vm/-/ethereumjs-vm-6.4.1-unofficial.0.tgz#8a6b10e08bde5fe80ad9a2e01fe1a0fa8ef74bf5" - integrity sha512-fkCKEjeYVyt/fuLmIERRGCtp/oaGbxd0rzgYCAgHJrGDKGB+LdvzvvyuMOUEbIRzE0jLe4OrDOrnSFLv6QjvVg== - dependencies: - "@ethereumjs/block" "4.2.1" - "@ethereumjs/blockchain" "6.2.1" - "@ethereumjs/common" "3.1.1" - "@ethereumjs/evm" "npm:@celo/ethereumjs-evm@1.3.1-unofficial.0" - "@ethereumjs/rlp" "4.0.1" - "@ethereumjs/statemanager" "1.0.4" - "@ethereumjs/trie" "5.0.4" - "@ethereumjs/tx" "4.1.1" - "@ethereumjs/util" "8.0.5" - debug "^4.3.3" - ethereum-cryptography "^1.1.2" - mcl-wasm "^0.7.1" - rustbn.js "~0.2.0" - -"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.0.0-beta.146", "@ethersproject/abi@^5.6.3", "@ethersproject/abi@^5.7.0": +"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.6.3", "@ethersproject/abi@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== @@ -1843,7 +1200,7 @@ dependencies: "@ethersproject/logger" "^5.7.0" -"@ethersproject/providers@5.7.2", "@ethersproject/providers@^5.7.1", "@ethersproject/providers@^5.7.2": +"@ethersproject/providers@5.7.2": version "5.7.2" resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== @@ -1994,55 +1351,11 @@ "@ethersproject/properties" "^5.7.0" "@ethersproject/strings" "^5.7.0" -"@ganache/console.log@0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@ganache/console.log/-/console.log-0.2.0.tgz#32ea0df806ed735d61bd0537d7b7fc350e511479" - integrity sha512-+SNBUZzrbe4DE4F0jdl9SU8w3ek5k4cUE73ttUFweo8FaKEDQsMbFjZ3ZU0LM6QM/zCMqE7euSq0s/IlsYxf7A== - dependencies: - "@ganache/utils" "0.3.0" - ethereumjs-util "7.1.5" - -"@ganache/console.log@0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@ganache/console.log/-/console.log-0.3.0.tgz#be7bb0875e883d7c219c3543cc7e854203c5233d" - integrity sha512-cRkjY3gn1zxPxy+PKK/xl12p3KbGwXeS7oGTkXFeey4bhQgd5QBa/+HNMVPflT2BcWLZ91Ir+CRRiRekeyHUWQ== - dependencies: - "@ethereumjs/util" "8.0.2" - "@ganache/utils" "0.3.0" - -"@ganache/utils@0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@ganache/utils/-/utils-0.3.0.tgz#f95d7a4746d4e062febf3ce59f65f6ca1336be8a" - integrity sha512-cxoG8KQxkYPl71BPdKZihjVKqN2AE7WLXjU65BVOQ5jEYrUH3CWSxA9v7CCUJj4e0HoXFpVFIZ+1HRkiBKKiKg== - dependencies: - emittery "0.10.0" - keccak "3.0.1" - seedrandom "3.0.5" - optionalDependencies: - "@trufflesuite/bigint-buffer" "1.1.9" - "@gar/promisify@^1.1.3": version "1.1.3" resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== -"@google-cloud/common@^0.32.0": - version "0.32.1" - resolved "https://registry.yarnpkg.com/@google-cloud/common/-/common-0.32.1.tgz#6a32c340172cea3db6674d0e0e34e78740a0073f" - integrity sha512-bLdPzFvvBMtVkwsoBtygE9oUm3yrNmPa71gvOgucYI/GqvNP2tb6RYsDHPq98kvignhcgHGDI5wyNgxaCo8bKQ== - dependencies: - "@google-cloud/projectify" "^0.3.3" - "@google-cloud/promisify" "^0.4.0" - "@types/request" "^2.48.1" - arrify "^2.0.0" - duplexify "^3.6.0" - ent "^2.2.0" - extend "^3.0.2" - google-auth-library "^3.1.1" - pify "^4.0.1" - retry-request "^4.0.0" - teeny-request "^3.11.3" - "@google-cloud/kms@~2.9.0": version "2.9.0" resolved "https://registry.yarnpkg.com/@google-cloud/kms/-/kms-2.9.0.tgz#3f7e51a3e30795a69ded4ea4f96609a59b503001" @@ -2050,237 +1363,43 @@ dependencies: google-gax "^2.24.1" -"@google-cloud/monitoring@0.7.1": - version "0.7.1" - resolved "https://registry.yarnpkg.com/@google-cloud/monitoring/-/monitoring-0.7.1.tgz#9afd2c8b237f01675dcaea8c5c7b3de9b58e24ad" - integrity sha512-RsBM/3pvlKvJdSuiMKU0cJ7XKZiMsrXvdY2AexK75659cou4SxhbqM60iaU9lqAbIcMcuhH8rc1AG3cRsDhYhQ== +"@grpc/grpc-js@^1.7.1": + version "1.9.7" + resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.9.7.tgz#7d0e29bc162287bee2523901c9bc9320d8402397" + integrity sha512-yMaA/cIsRhGzW3ymCNpdlPcInXcovztlgu/rirThj2b87u3RzWUszliOqZ/pldy7yhmJPS8uwog+kZSTa4A0PQ== dependencies: - google-gax "^0.25.0" - lodash.merge "^4.6.0" + "@grpc/proto-loader" "^0.7.8" + "@types/node" ">=12.12.47" -"@google-cloud/paginator@^0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@google-cloud/paginator/-/paginator-0.2.0.tgz#eab2e6aa4b81df7418f6c51e2071f64dab2c2fa5" - integrity sha512-2ZSARojHDhkLvQ+CS32K+iUhBsWg3AEw+uxtqblA7xoCABDyhpj99FPp35xy6A+XlzMhOSrHHaxFE+t6ZTQq0w== +"@grpc/grpc-js@~1.6.0": + version "1.6.12" + resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.6.12.tgz#20f710d8a8c5c396b2ae9530ba6c06b984614fdf" + integrity sha512-JmvQ03OTSpVd9JTlj/K3IWHSz4Gk/JMLUTtW7Zb0KvO1LcOYGATh5cNuRYzCAeDR3O8wq+q8FZe97eO9MBrkUw== dependencies: - arrify "^1.0.1" - extend "^3.0.1" - split-array-stream "^2.0.0" - stream-events "^1.0.4" - -"@google-cloud/precise-date@^0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@google-cloud/precise-date/-/precise-date-0.1.0.tgz#02ccda04b4413fa64f098fc93db51e95af5c855a" - integrity sha512-nXt4AskYjmDLRIO+nquVVppjiLE5ficFRP3WF1JYtPnSRFRpuMusa1kysPsD/yOxt5NMmvlkUCkaFI4rHYeckQ== - -"@google-cloud/projectify@^0.3.0", "@google-cloud/projectify@^0.3.3": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@google-cloud/projectify/-/projectify-0.3.3.tgz#bde9103d50b20a3ea3337df8c6783a766e70d41d" - integrity sha512-7522YHQ4IhaafgSunsFF15nG0TGVmxgXidy9cITMe+256RgqfcrfWphiMufW+Ou4kqagW/u3yxwbzVEW3dk2Uw== - -"@google-cloud/promisify@^0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@google-cloud/promisify/-/promisify-0.4.0.tgz#4fbfcf4d85bb6a2e4ccf05aa63d2b10d6c9aad9b" - integrity sha512-4yAHDC52TEMCNcMzVC8WlqnKKKq+Ssi2lXoUg9zWWkZ6U6tq9ZBRYLHHCRdfU+EU9YJsVmivwGcKYCjRGjnf4Q== - -"@google-cloud/pubsub@^0.28.1": - version "0.28.1" - resolved "https://registry.yarnpkg.com/@google-cloud/pubsub/-/pubsub-0.28.1.tgz#8d0605e155f5a8c36f7b51363c1e139f534b5fd8" - integrity sha512-ukvR2S6DgerEJ5T0e9G2XTyk83Ajjfhy2GdNHR3qOIkFZTn1VjqnMbGK8oWtnYm4+hZ9PHPiZY4LnxvapmwaRA== - dependencies: - "@google-cloud/paginator" "^0.2.0" - "@google-cloud/precise-date" "^0.1.0" - "@google-cloud/projectify" "^0.3.0" - "@google-cloud/promisify" "^0.4.0" - "@sindresorhus/is" "^0.15.0" - "@types/duplexify" "^3.6.0" - "@types/long" "^4.0.0" - "@types/p-defer" "^1.0.3" - arrify "^1.0.0" - async-each "^1.0.1" - extend "^3.0.1" - google-auth-library "^3.0.0" - google-gax "^0.25.0" - is-stream-ended "^0.1.4" - lodash.merge "^4.6.0" - lodash.snakecase "^4.1.1" - p-defer "^1.0.0" - protobufjs "^6.8.1" + "@grpc/proto-loader" "^0.7.0" + "@types/node" ">=12.12.47" -"@google-cloud/secret-manager@3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@google-cloud/secret-manager/-/secret-manager-3.0.0.tgz#31842287bd0eee380210488ae40cae3732b2b32f" - integrity sha512-ZAWoqiMbWv2Osx6Enq6TLPw/LR8kuSUWKhAsaJVy+q1GCR7clVNVuaPhizWIc4p88QYjW0h2j/wUBJ6OKFUmAw== +"@grpc/proto-loader@^0.6.12": + version "0.6.13" + resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.6.13.tgz#008f989b72a40c60c96cd4088522f09b05ac66bc" + integrity sha512-FjxPYDRTn6Ec3V0arm1FtSpmP6V50wuph2yILpyvTKzjc76oDdoihXqM1DzOW5ubvCC8GivfCnNtfaRE8myJ7g== dependencies: - google-gax "^2.0.1" + "@types/long" "^4.0.1" + lodash.camelcase "^4.3.0" + long "^4.0.0" + protobufjs "^6.11.3" + yargs "^16.2.0" -"@google-cloud/storage@^2.4.3": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@google-cloud/storage/-/storage-2.5.0.tgz#9dd3566d8155cf5ba0c212208f69f9ecd47fbd7e" - integrity sha512-q1mwB6RUebIahbA3eriRs8DbG2Ij81Ynb9k8hMqTPkmbd8/S6Z0d6hVvfPmnyvX9Ej13IcmEYIbymuq/RBLghA== - dependencies: - "@google-cloud/common" "^0.32.0" - "@google-cloud/paginator" "^0.2.0" - "@google-cloud/promisify" "^0.4.0" - arrify "^1.0.0" - async "^2.0.1" - compressible "^2.0.12" - concat-stream "^2.0.0" - date-and-time "^0.6.3" - duplexify "^3.5.0" - extend "^3.0.0" - gcs-resumable-upload "^1.0.0" - hash-stream-validation "^0.2.1" - mime "^2.2.0" - mime-types "^2.0.8" - onetime "^5.1.0" - pumpify "^1.5.1" - snakeize "^0.1.0" - stream-events "^1.0.1" - teeny-request "^3.11.3" - through2 "^3.0.0" - xdg-basedir "^3.0.0" - -"@graphql-tools/batch-execute@8.5.1": - version "8.5.1" - resolved "https://registry.yarnpkg.com/@graphql-tools/batch-execute/-/batch-execute-8.5.1.tgz#fa3321d58c64041650be44250b1ebc3aab0ba7a9" - integrity sha512-hRVDduX0UDEneVyEWtc2nu5H2PxpfSfM/riUlgZvo/a/nG475uyehxR5cFGvTEPEQUKY3vGIlqvtRigzqTfCew== +"@grpc/proto-loader@^0.7.0": + version "0.7.6" + resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.7.6.tgz#b71fdf92b184af184b668c4e9395a5ddc23d61de" + integrity sha512-QyAXR8Hyh7uMDmveWxDSUcJr9NAWaZ2I6IXgAYvQmfflwouTM+rArE2eEaCtLlRqO81j7pRLCt81IefUei6Zbw== dependencies: - "@graphql-tools/utils" "8.9.0" - dataloader "2.1.0" - tslib "^2.4.0" - value-or-promise "1.0.11" - -"@graphql-tools/delegate@^8.4.3": - version "8.8.1" - resolved "https://registry.yarnpkg.com/@graphql-tools/delegate/-/delegate-8.8.1.tgz#0653a72f38947f38ab7917dfac50ebf6a6b883e9" - integrity sha512-NDcg3GEQmdEHlnF7QS8b4lM1PSF+DKeFcIlLEfZFBvVq84791UtJcDj8734sIHLukmyuAxXMfA1qLd2l4lZqzA== - dependencies: - "@graphql-tools/batch-execute" "8.5.1" - "@graphql-tools/schema" "8.5.1" - "@graphql-tools/utils" "8.9.0" - dataloader "2.1.0" - tslib "~2.4.0" - value-or-promise "1.0.11" - -"@graphql-tools/merge@8.3.1": - version "8.3.1" - resolved "https://registry.yarnpkg.com/@graphql-tools/merge/-/merge-8.3.1.tgz#06121942ad28982a14635dbc87b5d488a041d722" - integrity sha512-BMm99mqdNZbEYeTPK3it9r9S6rsZsQKtlqJsSBknAclXq2pGEfOxjcIZi+kBSkHZKPKCRrYDd5vY0+rUmIHVLg== - dependencies: - "@graphql-tools/utils" "8.9.0" - tslib "^2.4.0" - -"@graphql-tools/merge@^8.4.1": - version "8.4.2" - resolved "https://registry.yarnpkg.com/@graphql-tools/merge/-/merge-8.4.2.tgz#95778bbe26b635e8d2f60ce9856b388f11fe8288" - integrity sha512-XbrHAaj8yDuINph+sAfuq3QCZ/tKblrTLOpirK0+CAgNlZUCHs0Fa+xtMUURgwCVThLle1AF7svJCxFizygLsw== - dependencies: - "@graphql-tools/utils" "^9.2.1" - tslib "^2.4.0" - -"@graphql-tools/mock@^8.1.2": - version "8.7.20" - resolved "https://registry.yarnpkg.com/@graphql-tools/mock/-/mock-8.7.20.tgz#c83ae0f1940d194a3982120c9c85f3ac6b4f7f20" - integrity sha512-ljcHSJWjC/ZyzpXd5cfNhPI7YljRVvabKHPzKjEs5ElxWu2cdlLGvyNYepApXDsM/OJG/2xuhGM+9GWu5gEAPQ== - dependencies: - "@graphql-tools/schema" "^9.0.18" - "@graphql-tools/utils" "^9.2.1" - fast-json-stable-stringify "^2.1.0" - tslib "^2.4.0" - -"@graphql-tools/schema@8.5.1", "@graphql-tools/schema@^8.0.0", "@graphql-tools/schema@^8.3.1": - version "8.5.1" - resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-8.5.1.tgz#c2f2ff1448380919a330312399c9471db2580b58" - integrity sha512-0Esilsh0P/qYcB5DKQpiKeQs/jevzIadNTaT0jeWklPMwNbT7yMX4EqZany7mbeRRlSRwMzNzL5olyFdffHBZg== - dependencies: - "@graphql-tools/merge" "8.3.1" - "@graphql-tools/utils" "8.9.0" - tslib "^2.4.0" - value-or-promise "1.0.11" - -"@graphql-tools/schema@^9.0.18": - version "9.0.19" - resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-9.0.19.tgz#c4ad373b5e1b8a0cf365163435b7d236ebdd06e7" - integrity sha512-oBRPoNBtCkk0zbUsyP4GaIzCt8C0aCI4ycIRUL67KK5pOHljKLBBtGT+Jr6hkzA74C8Gco8bpZPe7aWFjiaK2w== - dependencies: - "@graphql-tools/merge" "^8.4.1" - "@graphql-tools/utils" "^9.2.1" - tslib "^2.4.0" - value-or-promise "^1.0.12" - -"@graphql-tools/utils@8.9.0": - version "8.9.0" - resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-8.9.0.tgz#c6aa5f651c9c99e1aca55510af21b56ec296cdb7" - integrity sha512-pjJIWH0XOVnYGXCqej8g/u/tsfV4LvLlj0eATKQu5zwnxd/TiTHq7Cg313qUPTFFHZ3PP5wJ15chYVtLDwaymg== - dependencies: - tslib "^2.4.0" - -"@graphql-tools/utils@^9.2.1": - version "9.2.1" - resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-9.2.1.tgz#1b3df0ef166cfa3eae706e3518b17d5922721c57" - integrity sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A== - dependencies: - "@graphql-typed-document-node/core" "^3.1.1" - tslib "^2.4.0" - -"@graphql-typed-document-node/core@^3.1.1": - version "3.2.0" - resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861" - integrity sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ== - -"@grpc/grpc-js@^0.3.0": - version "0.3.6" - resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-0.3.6.tgz#d9b52043907170d38e06711d9477fde29ab46fa8" - integrity sha512-SmLNuPGlUur64bNS9aHZguqWDVQ8+Df1CGn+xsh7l6T2wiP5ArOMlywZ3TZo6z/rwKtGQgUJY9ZrPYUmHEXd/Q== - dependencies: - semver "^5.5.0" - -"@grpc/grpc-js@^1.7.1": - version "1.9.7" - resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.9.7.tgz#7d0e29bc162287bee2523901c9bc9320d8402397" - integrity sha512-yMaA/cIsRhGzW3ymCNpdlPcInXcovztlgu/rirThj2b87u3RzWUszliOqZ/pldy7yhmJPS8uwog+kZSTa4A0PQ== - dependencies: - "@grpc/proto-loader" "^0.7.8" - "@types/node" ">=12.12.47" - -"@grpc/grpc-js@~1.6.0": - version "1.6.12" - resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.6.12.tgz#20f710d8a8c5c396b2ae9530ba6c06b984614fdf" - integrity sha512-JmvQ03OTSpVd9JTlj/K3IWHSz4Gk/JMLUTtW7Zb0KvO1LcOYGATh5cNuRYzCAeDR3O8wq+q8FZe97eO9MBrkUw== - dependencies: - "@grpc/proto-loader" "^0.7.0" - "@types/node" ">=12.12.47" - -"@grpc/proto-loader@^0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.4.0.tgz#a823a51eb2fde58369bef1deb5445fd808d70901" - integrity sha512-Jm6o+75uWT7E6+lt8edg4J1F/9+BedOjaMgwE14pxS/AO43/0ZqK+rCLVVrXLoExwSAZvgvOD2B0ivy3Spsspw== - dependencies: - lodash.camelcase "^4.3.0" - protobufjs "^6.8.6" - -"@grpc/proto-loader@^0.6.12": - version "0.6.13" - resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.6.13.tgz#008f989b72a40c60c96cd4088522f09b05ac66bc" - integrity sha512-FjxPYDRTn6Ec3V0arm1FtSpmP6V50wuph2yILpyvTKzjc76oDdoihXqM1DzOW5ubvCC8GivfCnNtfaRE8myJ7g== - dependencies: - "@types/long" "^4.0.1" - lodash.camelcase "^4.3.0" - long "^4.0.0" - protobufjs "^6.11.3" - yargs "^16.2.0" - -"@grpc/proto-loader@^0.7.0": - version "0.7.6" - resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.7.6.tgz#b71fdf92b184af184b668c4e9395a5ddc23d61de" - 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" + "@types/long" "^4.0.1" + lodash.camelcase "^4.3.0" + long "^4.0.0" + protobufjs "^7.0.0" + yargs "^16.2.0" "@grpc/proto-loader@^0.7.8": version "0.7.10" @@ -2368,18 +1487,6 @@ resolved "https://registry.yarnpkg.com/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz#98c23c950a3d9b6c8f0daed06da6c3af06981340" integrity sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q== -"@isaacs/cliui@^8.0.2": - version "8.0.2" - resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" - integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== - dependencies: - string-width "^5.1.2" - string-width-cjs "npm:string-width@^4.2.0" - strip-ansi "^7.0.1" - strip-ansi-cjs "npm:strip-ansi@^6.0.1" - wrap-ansi "^8.1.0" - wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" - "@isaacs/string-locale-compare@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@isaacs/string-locale-compare/-/string-locale-compare-1.1.0.tgz#291c227e93fd407a96ecd59879a35809120e432b" @@ -2593,11 +1700,6 @@ "@types/yargs" "^17.0.8" chalk "^4.0.0" -"@josephg/resolvable@^1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@josephg/resolvable/-/resolvable-1.0.1.tgz#69bc4db754d79e1a2f17a650d3466e038d94a5eb" - integrity sha512-CtzORUwWTTOTqfVtHaKRJ0I1kNQd1bpn3sUh8I3nJDVY+5/M/Oe1DnEWzPQvqq/xPIIkzzzIP7mfCoAjFRvDhg== - "@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": version "0.3.3" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" @@ -2648,13 +1750,6 @@ "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" -"@ledgerhq/cryptoassets@^5.53.0": - version "5.53.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/cryptoassets/-/cryptoassets-5.53.0.tgz#11dcc93211960c6fd6620392e4dd91896aaabe58" - integrity sha512-M3ibc3LRuHid5UtL7FI3IC6nMEppvly98QHFoSa7lJU0HDzQxY6zHec/SPM4uuJUC8sXoGVAiRJDkgny54damw== - dependencies: - invariant "2" - "@ledgerhq/devices@^5.11.0", "@ledgerhq/devices@^5.51.1": version "5.51.1" resolved "https://registry.yarnpkg.com/@ledgerhq/devices/-/devices-5.51.1.tgz#d741a4a5d8f17c2f9d282fd27147e6fe1999edb7" @@ -2685,18 +1780,6 @@ resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-6.12.4.tgz#1c2f75dc3dee91b069f3446be484fa28676d1b45" integrity sha512-qi5poMrcIuFuivdzRjjQsNp7rRwUA5v3eo6D4yEy+l+w8wT4d4JtQ5u1TbrlGfFHfgLq7Lv6dsvh2ooLyWTyfg== -"@ledgerhq/hw-app-eth@^5.53.0": - version "5.53.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-eth/-/hw-app-eth-5.53.0.tgz#5df2d7427db9f387099d0cc437e9730101d7c404" - integrity sha512-LKi/lDA9tW0GdoYP1ng0VY/PXNYjSrwZ1cj0R0MQ9z+knmFlPcVkGK2MEqE8W8cXrC0tjsUXITMcngvpk5yfKA== - dependencies: - "@ledgerhq/cryptoassets" "^5.53.0" - "@ledgerhq/errors" "^5.50.0" - "@ledgerhq/hw-transport" "^5.51.1" - "@ledgerhq/logs" "^5.50.0" - bignumber.js "^9.0.1" - ethers "^5.2.0" - "@ledgerhq/hw-app-eth@~5.11.0": version "5.11.0" resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-eth/-/hw-app-eth-5.11.0.tgz#5db6abe0ddf5b5266ed09868de12021f59c1a33e" @@ -2705,17 +1788,6 @@ "@ledgerhq/errors" "^5.11.0" "@ledgerhq/hw-transport" "^5.11.0" -"@ledgerhq/hw-transport-node-hid-noevents@^5.51.1": - version "5.51.1" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid-noevents/-/hw-transport-node-hid-noevents-5.51.1.tgz#71f37f812e448178ad0bcc2258982150d211c1ab" - integrity sha512-9wFf1L8ZQplF7XOY2sQGEeOhpmBRzrn+4X43kghZ7FBDoltrcK+s/D7S+7ffg3j2OySyP6vIIIgloXylao5Scg== - dependencies: - "@ledgerhq/devices" "^5.51.1" - "@ledgerhq/errors" "^5.50.0" - "@ledgerhq/hw-transport" "^5.51.1" - "@ledgerhq/logs" "^5.50.0" - node-hid "2.1.1" - "@ledgerhq/hw-transport-node-hid-noevents@^6.27.13": version "6.27.13" resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid-noevents/-/hw-transport-node-hid-noevents-6.27.13.tgz#96f3667a18ea3602160af5d08db677ae0b8e3bb7" @@ -2727,20 +1799,6 @@ "@ledgerhq/logs" "^6.10.1" node-hid "^2.1.2" -"@ledgerhq/hw-transport-node-hid@^5.51.1": - version "5.51.1" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-5.51.1.tgz#fe8eb81e18929663540698c80905952cdbe542d5" - integrity sha512-Y2eVCCdhVs2Lfr7N2x2cNb+ogcZ24ZATO4QxaQ7LogjiPwYmzmvuXFn8zFjMSrKUCn9CtbptXcuiu0NkGsjWlw== - dependencies: - "@ledgerhq/devices" "^5.51.1" - "@ledgerhq/errors" "^5.50.0" - "@ledgerhq/hw-transport" "^5.51.1" - "@ledgerhq/hw-transport-node-hid-noevents" "^5.51.1" - "@ledgerhq/logs" "^5.50.0" - lodash "^4.17.21" - node-hid "2.1.1" - usb "^1.7.0" - "@ledgerhq/hw-transport-node-hid@^6.27.4": version "6.27.13" resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-6.27.13.tgz#741644d7b8761f682b36eda36e1bf7876357efda" @@ -2755,17 +1813,7 @@ node-hid "^2.1.2" usb "^1.7.0" -"@ledgerhq/hw-transport-webusb@^5.53.1": - version "5.53.1" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-webusb/-/hw-transport-webusb-5.53.1.tgz#3df8c401417571e3bcacc378d8aca587214b05ae" - integrity sha512-A/f+xcrkIAZiJrvPpDvsrjxQX4cI2kbdiunQkwsYmOG3Bp4z89ZnsBiC7YBst4n2/g+QgTg0/KPVtODU5djooQ== - dependencies: - "@ledgerhq/devices" "^5.51.1" - "@ledgerhq/errors" "^5.50.0" - "@ledgerhq/hw-transport" "^5.51.1" - "@ledgerhq/logs" "^5.50.0" - -"@ledgerhq/hw-transport@^5.11.0", "@ledgerhq/hw-transport@^5.51.1": +"@ledgerhq/hw-transport@^5.11.0": version "5.51.1" resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-5.51.1.tgz#8dd14a8e58cbee4df0c29eaeef983a79f5f22578" integrity sha512-6wDYdbWrw9VwHIcoDnqWBaDFyviyjZWv6H9vz9Vyhe4Qd7TIFmbTl/eWs6hZvtZBza9K8y7zD8ChHwRI4s9tSw== @@ -3508,11 +2556,6 @@ globby "^11.0.0" read-yaml-file "^1.1.0" -"@metamask/safe-event-emitter@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@metamask/safe-event-emitter/-/safe-event-emitter-2.0.0.tgz#af577b477c683fad17c619a78208cede06f9605c" - integrity sha512-/kSXhY692qiV1MXu6EeOZvg5nECLclxNXcKCxJ3cXQgYuRymRHpdx/t7JXfsK+JLjwA1e1c1/SBrlQYpusC29Q== - "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1" resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" @@ -3535,13 +2578,6 @@ dependencies: "@noble/hashes" "1.3.1" -"@noble/curves@1.2.0", "@noble/curves@~1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35" - integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw== - dependencies: - "@noble/hashes" "1.3.2" - "@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" @@ -3557,7 +2593,7 @@ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9" integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA== -"@noble/hashes@1.3.2", "@noble/hashes@~1.3.0", "@noble/hashes@~1.3.1", "@noble/hashes@~1.3.2": +"@noble/hashes@~1.3.0", "@noble/hashes@~1.3.1": version "1.3.2" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== @@ -4884,32 +3920,6 @@ dependencies: "@opentelemetry/core" "^1.1.0" -"@openzeppelin/contracts8@npm:@openzeppelin/contracts@^4.4.2": - version "4.9.1" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.9.1.tgz#afa804d2c68398704b0175acc94d91a54f203645" - integrity sha512-aLDTLu/If1qYIFW5g4ZibuQaUsFGWQPBq1mZKp/txaebUnGHDmmiBhRLY1tDNedN0m+fJtKZ1zAODS9Yk+V6uA== - -"@openzeppelin/upgrades@^2.8.0": - version "2.8.0" - resolved "https://registry.yarnpkg.com/@openzeppelin/upgrades/-/upgrades-2.8.0.tgz#8086ab9c99d9f8dac7205030b0f9e7e4a280c4a3" - integrity sha512-LzjTQPeljPsgHDPdZyH9cMCbIHZILgd2cpNcYEkdsC2IylBYRHShlbEDXJV9snnqg9JWfzPiKIqyj3XVliwtqQ== - dependencies: - "@types/cbor" "^2.0.0" - axios "^0.18.0" - bignumber.js "^7.2.0" - cbor "^4.1.5" - chalk "^2.4.1" - ethers "^4.0.20" - glob "^7.1.3" - lodash "^4.17.15" - semver "^5.5.1" - spinnies "^0.4.2" - truffle-flattener "^1.4.0" - web3 "1.2.2" - web3-eth "1.2.2" - web3-eth-contract "1.2.2" - web3-utils "1.2.2" - "@parcel/watcher@2.0.4": version "2.0.4" resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.0.4.tgz#f300fef4cc38008ff4b8c29d92588eced3ce014b" @@ -4918,11 +3928,6 @@ node-addon-api "^3.2.1" node-gyp-build "^4.3.0" -"@pkgjs/parseargs@^0.11.0": - version "0.11.0" - resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" - integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== - "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" @@ -4976,94 +3981,11 @@ resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== -"@redux-saga/core@^1.0.0": - version "1.2.3" - resolved "https://registry.yarnpkg.com/@redux-saga/core/-/core-1.2.3.tgz#882ed9ac58b5f42c6abb23349542315b871de305" - integrity sha512-U1JO6ncFBAklFTwoQ3mjAeQZ6QGutsJzwNBjgVLSWDpZTRhobUzuVDS1qH3SKGJD8fvqoaYOjp6XJ3gCmeZWgA== - dependencies: - "@babel/runtime" "^7.6.3" - "@redux-saga/deferred" "^1.2.1" - "@redux-saga/delay-p" "^1.2.1" - "@redux-saga/is" "^1.1.3" - "@redux-saga/symbols" "^1.1.3" - "@redux-saga/types" "^1.2.1" - redux "^4.0.4" - typescript-tuple "^2.2.1" - -"@redux-saga/deferred@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@redux-saga/deferred/-/deferred-1.2.1.tgz#aca373a08ccafd6f3481037f2f7ee97f2c87c3ec" - integrity sha512-cmin3IuuzMdfQjA0lG4B+jX+9HdTgHZZ+6u3jRAOwGUxy77GSlTi4Qp2d6PM1PUoTmQUR5aijlA39scWWPF31g== - -"@redux-saga/delay-p@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@redux-saga/delay-p/-/delay-p-1.2.1.tgz#e72ac4731c5080a21f75b61bedc31cb639d9e446" - integrity sha512-MdiDxZdvb1m+Y0s4/hgdcAXntpUytr9g0hpcOO1XFVyyzkrDu3SKPgBFOtHn7lhu7n24ZKIAT1qtKyQjHqRd+w== - dependencies: - "@redux-saga/symbols" "^1.1.3" - -"@redux-saga/is@^1.1.3": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@redux-saga/is/-/is-1.1.3.tgz#b333f31967e87e32b4e6b02c75b78d609dd4ad73" - integrity sha512-naXrkETG1jLRfVfhOx/ZdLj0EyAzHYbgJWkXbB3qFliPcHKiWbv/ULQryOAEKyjrhiclmr6AMdgsXFyx7/yE6Q== - dependencies: - "@redux-saga/symbols" "^1.1.3" - "@redux-saga/types" "^1.2.1" - -"@redux-saga/symbols@^1.1.3": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@redux-saga/symbols/-/symbols-1.1.3.tgz#b731d56201719e96dc887dc3ae9016e761654367" - integrity sha512-hCx6ZvU4QAEUojETnX8EVg4ubNLBFl1Lps4j2tX7o45x/2qg37m3c6v+kSp8xjDJY+2tJw4QB3j8o8dsl1FDXg== - -"@redux-saga/types@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@redux-saga/types/-/types-1.2.1.tgz#9403f51c17cae37edf870c6bc0c81c1ece5ccef8" - integrity sha512-1dgmkh+3so0+LlBWRhGA33ua4MYr7tUOj+a9Si28vUi0IUFNbff1T3sgpeDJI/LaC75bBYnQ0A3wXjn0OrRNBA== - -"@resolver-engine/core@^0.2.1": - version "0.2.1" - resolved "https://registry.yarnpkg.com/@resolver-engine/core/-/core-0.2.1.tgz#0d71803f6d3b8cb2e9ed481a1bf0ca5f5256d0c0" - integrity sha512-nsLQHmPJ77QuifqsIvqjaF5B9aHnDzJjp73Q1z6apY3e9nqYrx4Dtowhpsf7Jwftg/XzVDEMQC+OzUBNTS+S1A== - dependencies: - debug "^3.1.0" - request "^2.85.0" - -"@resolver-engine/fs@^0.2.1": - version "0.2.1" - resolved "https://registry.yarnpkg.com/@resolver-engine/fs/-/fs-0.2.1.tgz#f98a308d77568cc02651d03636f46536b941b241" - integrity sha512-7kJInM1Qo2LJcKyDhuYzh9ZWd+mal/fynfL9BNjWOiTcOpX+jNfqb/UmGUqros5pceBITlWGqS4lU709yHFUbg== - dependencies: - "@resolver-engine/core" "^0.2.1" - debug "^3.1.0" - -"@resolver-engine/imports-fs@^0.2.2": - version "0.2.2" - resolved "https://registry.yarnpkg.com/@resolver-engine/imports-fs/-/imports-fs-0.2.2.tgz#5a81ef3285dbf0411ab3b15205080a1ad7622d9e" - integrity sha512-gFCgMvCwyppjwq0UzIjde/WI+yDs3oatJhozG9xdjJdewwtd7LiF0T5i9lrHAUtqrQbqoFE4E+ZMRVHWpWHpKQ== - dependencies: - "@resolver-engine/fs" "^0.2.1" - "@resolver-engine/imports" "^0.2.2" - debug "^3.1.0" - -"@resolver-engine/imports@^0.2.2": - version "0.2.2" - resolved "https://registry.yarnpkg.com/@resolver-engine/imports/-/imports-0.2.2.tgz#d3de55a1bb5f3beb7703fdde743298f321175843" - integrity sha512-u5/HUkvo8q34AA+hnxxqqXGfby5swnH0Myw91o3Sm2TETJlNKXibFGSKBavAH+wvWdBi4Z5gS2Odu0PowgVOUg== - dependencies: - "@resolver-engine/core" "^0.2.1" - debug "^3.1.0" - hosted-git-info "^2.6.0" - "@scure/base@~1.1.0": version "1.1.1" resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938" integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA== -"@scure/base@~1.1.2": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.3.tgz#8584115565228290a6c6c4961973e0903bb3df2f" - integrity sha512-/+SgoRjLq7Xlf0CWuLHq2LUZeL/w65kfzAPG5NH9pcmBhs+nunQTn4gvdwgMTIXnt9b2C/1SeL2XiysZEyIC9Q== - "@scure/bip32@1.1.5": version "1.1.5" resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.1.5.tgz#d2ccae16dcc2e75bc1d75f5ef3c66a338d1ba300" @@ -5091,15 +4013,6 @@ "@noble/hashes" "~1.3.1" "@scure/base" "~1.1.0" -"@scure/bip32@1.3.2": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.2.tgz#90e78c027d5e30f0b22c1f8d50ff12f3fb7559f8" - integrity sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA== - dependencies: - "@noble/curves" "~1.2.0" - "@noble/hashes" "~1.3.2" - "@scure/base" "~1.1.2" - "@scure/bip39@1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.1.tgz#b54557b2e86214319405db819c4b6a370cf340c5" @@ -5146,16 +4059,6 @@ resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.25.24.tgz#8c7688559979f7079aacaf31aa881c3aa410b718" integrity sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ== -"@sindresorhus/is@^0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" - integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== - -"@sindresorhus/is@^0.15.0": - version "0.15.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.15.0.tgz#96915baa05e6a6a1d137badf4984d3fc05820bb6" - integrity sha512-lu8BpxjAtRCAo5ifytTpCPCj99LF7o/2Myn+NXyNCBqvPYn7Pjd76AMmUB5l7XF1U6t0hcWrlEM5ESufW7wAeA== - "@sindresorhus/is@^4.0.0", "@sindresorhus/is@^4.6.0": version "4.6.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" @@ -5175,20 +4078,6 @@ dependencies: "@sinonjs/commons" "^2.0.0" -"@solidity-parser/parser@^0.14.0", "@solidity-parser/parser@^0.14.1": - version "0.14.5" - resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.14.5.tgz#87bc3cc7b068e08195c219c91cd8ddff5ef1a804" - integrity sha512-6dKnHZn7fg/iQATVEzqyUOyEidbn05q7YA2mQ9hC0MMXhhV3/JrsxmFSYZAcr7j1yUP700LLhTruvJ3MiQmjJg== - dependencies: - antlr4ts "^0.5.0-alpha.4" - -"@solidity-parser/parser@^0.16.0": - version "0.16.0" - resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.16.0.tgz#1fb418c816ca1fc3a1e94b08bcfe623ec4e1add4" - integrity sha512-ESipEcHyRHg4Np4SqBCfcXwyxxna1DgFVz69bgpLV8vzl/NP1DtcKsJ4dJZXWQhY/Z4J2LeKBiOkOVZn9ct33Q== - dependencies: - antlr4ts "^0.5.0-alpha.4" - "@stablelib/binary@^0.7.2": version "0.7.2" resolved "https://registry.yarnpkg.com/@stablelib/binary/-/binary-0.7.2.tgz#1b3392170c8a8741c8b8f843ea294de71aeb2cf7" @@ -5229,18 +4118,6 @@ resolved "https://registry.yarnpkg.com/@stablelib/wipe/-/wipe-0.5.0.tgz#a682d5f9448e950e099e537e6f72fc960275d151" integrity sha512-SifvRV0rTTFR1qEF6G1hondGZyrmiM1laR8PPrO6TZwQG03hJduVbUX8uQk+Q6FdkND2Z9B8uLPyUAquQIk3iA== -"@summa-tx/memview.sol@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@summa-tx/memview.sol/-/memview.sol-1.1.0.tgz#f54a09faef46ca52deb94e10d0daacd28efe5be6" - integrity sha512-nLEfdC0ayn+PND5WWGalv+IyQ0NYomz43s1IJWDjawUh4JvW03LeP7ZjuMJPLdyJqYX3p8x1LwYt8Klde7cluw== - -"@szmarczak/http-timer@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" - integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== - dependencies: - defer-to-connect "^1.0.1" - "@szmarczak/http-timer@^4.0.5": version "4.0.6" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807" @@ -5265,25 +4142,7 @@ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== -"@truffle/abi-utils@^0.3.0", "@truffle/abi-utils@^0.3.9": - version "0.3.9" - resolved "https://registry.yarnpkg.com/@truffle/abi-utils/-/abi-utils-0.3.9.tgz#c476f5cfe01072b513b3e93fd7bea05cf7bd9d96" - integrity sha512-G5dqgwRHx5zwlXjz3QT8OJVfB2cOqWwD6DwKso0KttUt/zejhCjnkKq72rSgyeLMkz7wBB9ERLOsupLBILM8MA== - dependencies: - change-case "3.0.2" - fast-check "3.1.1" - web3-utils "1.8.2" - -"@truffle/abi-utils@^0.3.10": - version "0.3.10" - resolved "https://registry.yarnpkg.com/@truffle/abi-utils/-/abi-utils-0.3.10.tgz#693684d6cd3e86bd48ddbf615cd159156fac1605" - integrity sha512-Q3TXsF0NIct3KFLL2giF/alfSoKf5axyw+4wQdDRlihFrG1nbTBzWq+Q0ya6oHffZDida0NSpnJIf5IhFMV+JQ== - dependencies: - change-case "3.0.2" - fast-check "3.1.1" - web3-utils "1.10.0" - -"@truffle/abi-utils@^1.0.0", "@truffle/abi-utils@^1.0.3": +"@truffle/abi-utils@^1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@truffle/abi-utils/-/abi-utils-1.0.3.tgz#9f0df7a8aaf5e815bee47e0ad26bd4c91e4045f2" integrity sha512-AWhs01HCShaVKjml7Z4AbVREr/u4oiWxCcoR7Cktm0mEvtT04pvnxW5xB/cI4znRkrbPdFQlFt67kgrAjesYkw== @@ -5292,73 +4151,11 @@ fast-check "3.1.1" web3-utils "1.10.0" -"@truffle/artifactor@4.0.180": - version "4.0.180" - resolved "https://registry.yarnpkg.com/@truffle/artifactor/-/artifactor-4.0.180.tgz#5dded58d923d5c2e6442d09d4d3d3d9b10646c05" - integrity sha512-XWY1w5KMYsYQ9XN+QbR5W95HXLKumxdi3so70SRUkmmEx9+vTlvhzJ/aeyCtuOzRO6WjdZ6pOaUxMNcW5BqQDg== - dependencies: - "@truffle/contract-schema" "^3.4.11" - fs-extra "^9.1.0" - lodash "^4.17.21" - -"@truffle/artifactor@^4.0.36": - version "4.0.188" - resolved "https://registry.yarnpkg.com/@truffle/artifactor/-/artifactor-4.0.188.tgz#2197300fd61a4196f2be9599fc0bb82e5d0b1817" - integrity sha512-PqSiLHLGyWhoRWt6dimXBM5JsEXvVY3KejSEw3g8X+QInyNTivwSpHQMdP+9avVWkRjX8OltRAbg5i3fzS1Suw== - dependencies: - "@truffle/contract-schema" "^3.4.13" - fs-extra "^9.1.0" - lodash "^4.17.21" - -"@truffle/blockchain-utils@^0.1.6", "@truffle/blockchain-utils@^0.1.7": - version "0.1.7" - resolved "https://registry.yarnpkg.com/@truffle/blockchain-utils/-/blockchain-utils-0.1.7.tgz#cf7923a3ae5b591ae4c2a5ee45994a310ccaf1ee" - integrity sha512-1nibqGjEHC7KAyDThEFvbm2+EO8zAHee/VjCtxkYBE3ySwP50joh0QCEBjy7K/9z+icpMoDucfxmgaKToBFUgQ== - "@truffle/blockchain-utils@^0.1.9": version "0.1.9" resolved "https://registry.yarnpkg.com/@truffle/blockchain-utils/-/blockchain-utils-0.1.9.tgz#d9b55bd23a134578e4217bae55a6dfbbb038d6dc" integrity sha512-RHfumgbIVo68Rv9ofDYfynjnYZIfP/f1vZy4RoqkfYAO+fqfc58PDRzB1WAGq2U6GPuOnipOJxQhnqNnffORZg== -"@truffle/code-utils@^3.0.2": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@truffle/code-utils/-/code-utils-3.0.2.tgz#603b0662a1fc27d24a92aaf66417559a3f3e3915" - integrity sha512-Q4FyYIX9G4GyMa8RJDk19kvgiyGZ1CGEx2RmVcXoCDZqEyiHLzqjvCRp+/fuBz2fv7szO6d+60LO1gLCGS1drQ== - dependencies: - cbor "^5.2.0" - -"@truffle/codec@^0.14.17": - version "0.14.17" - resolved "https://registry.yarnpkg.com/@truffle/codec/-/codec-0.14.17.tgz#4ab11fab335854dad0d4aef75db2960ebd76fcd8" - integrity sha512-kD4dD86huLeaBEq5R8D1zleJEu6NsXbyYLdXl1V1TKdiO8odw5CBC6Y/+wdu5d3t1dyEYrTbhn1dqknZa52pmw== - dependencies: - "@truffle/abi-utils" "^0.3.9" - "@truffle/compile-common" "^0.9.4" - big.js "^6.0.3" - bn.js "^5.1.3" - cbor "^5.2.0" - debug "^4.3.1" - lodash "^4.17.21" - semver "7.3.7" - utf8 "^3.0.0" - web3-utils "1.8.2" - -"@truffle/codec@^0.15.0": - version "0.15.0" - resolved "https://registry.yarnpkg.com/@truffle/codec/-/codec-0.15.0.tgz#c6dffe4c5f779dbc5187cc13aa99a5350377fe97" - integrity sha512-FEcwtDUuMr85a9u39eqvNgmUgXDvIkwhJjMCCi/bC4/GmLisOpih8vAidDgdYMJldukMPaOX5XIIgsG5k615YA== - dependencies: - "@truffle/abi-utils" "^0.3.10" - "@truffle/compile-common" "^0.9.4" - big.js "^6.0.3" - bn.js "^5.1.3" - cbor "^5.2.0" - debug "^4.3.1" - lodash "^4.17.21" - semver "7.3.7" - utf8 "^3.0.0" - web3-utils "1.10.0" - "@truffle/codec@^0.17.3": version "0.17.3" resolved "https://registry.yarnpkg.com/@truffle/codec/-/codec-0.17.3.tgz#94057e56e1a947594b35eba498d96915df3861d2" @@ -5375,24 +4172,6 @@ utf8 "^3.0.0" web3-utils "1.10.0" -"@truffle/compile-common@^0.3.9": - version "0.3.12" - resolved "https://registry.yarnpkg.com/@truffle/compile-common/-/compile-common-0.3.12.tgz#73e3849aa61de1f98596b440f0bfce7e3063c2e4" - integrity sha512-X4mnCiaoUD9+0XL7HYF3I+nW3EXggj207DF1uOJUSrS/wjIbs2eqUo1aqMPp0uw0o3Ek2EpDLq9w5Jm3myHLqw== - dependencies: - "@truffle/contract-schema" "^3.2.5" - fs-extra "^8.1.0" - mocha "8.0.1" - ts-node "8.10.2" - -"@truffle/compile-common@^0.9.4": - version "0.9.4" - resolved "https://registry.yarnpkg.com/@truffle/compile-common/-/compile-common-0.9.4.tgz#064208cda70491692b538f717809bb904a122c20" - integrity sha512-mnqJB/hLiPHNf+WKwt/2MH6lv34xSG/SFCib7+ckAklutUqVLeFo8EwQxinuHNkU7LY0C+YgZXhK1WTCO5YRJQ== - dependencies: - "@truffle/error" "^0.2.0" - colors "1.4.0" - "@truffle/compile-common@^0.9.8": version "0.9.8" resolved "https://registry.yarnpkg.com/@truffle/compile-common/-/compile-common-0.9.8.tgz#f91507c895852289a17bf401eefebc293c4c69f0" @@ -5401,131 +4180,6 @@ "@truffle/error" "^0.2.2" colors "1.4.0" -"@truffle/compile-solidity@^4.3.22": - version "4.3.22" - resolved "https://registry.yarnpkg.com/@truffle/compile-solidity/-/compile-solidity-4.3.22.tgz#b9f0b8834c8095f7d91e4061e1fa67994752d506" - integrity sha512-hYogrD836KhM4V6YED15ioS7NtmfiermgXqZpTtMJcy5klf0Q2tLhVg96dcOZsHM26tNV9wiJPSViJhLN0PNjw== - dependencies: - "@truffle/compile-common" "^0.3.9" - "@truffle/config" "^1.2.29" - "@truffle/contract-sources" "^0.1.8" - "@truffle/error" "^0.0.11" - "@truffle/expect" "^0.0.15" - colors "^1.1.2" - debug "^4.1.0" - fs-extra "^8.1.0" - ora "^3.4.0" - original-require "^1.0.1" - request "^2.85.0" - request-promise "^4.2.2" - require-from-string "^2.0.2" - semver "^5.6.0" - solc "^0.6.0" - -"@truffle/compile-solidity@^6.0.54": - version "6.0.66" - resolved "https://registry.yarnpkg.com/@truffle/compile-solidity/-/compile-solidity-6.0.66.tgz#28b432a90766d49530bba6371a7a00f8246e79d9" - integrity sha512-IAOSBRf32kI6SzD3G9ZA8D6Df96TX2G+XW9m8tKEUghYk38NCTqKTg13u6GKrIuDrtTzWw/f/Eq8mn0bTdDoig== - dependencies: - "@truffle/compile-common" "^0.9.4" - "@truffle/config" "^1.3.55" - "@truffle/contract-sources" "^0.2.0" - "@truffle/expect" "^0.1.5" - "@truffle/profiler" "^0.1.47" - axios "1.2.4" - axios-retry "^3.1.9" - debug "^4.3.1" - fs-extra "^9.1.0" - iter-tools "^7.0.2" - lodash "^4.17.21" - node-abort-controller "^3.0.1" - original-require "^1.0.1" - require-from-string "^2.0.2" - semver "7.3.7" - solc "0.8.19" - -"@truffle/compile-solidity@^6.0.79": - version "6.0.79" - resolved "https://registry.yarnpkg.com/@truffle/compile-solidity/-/compile-solidity-6.0.79.tgz#65007b072bd5b32984858b27cd1a72c7c45e50ef" - integrity sha512-sdKYTrXwNr70p17MOzkV277ayNA7evECPFRGTvi6qDea697EXTqq694coH1ffmSjArhrqpinMMenF1v421A/AA== - dependencies: - "@truffle/compile-common" "^0.9.8" - "@truffle/config" "^1.3.61" - "@truffle/contract-sources" "^0.2.1" - "@truffle/expect" "^0.1.7" - "@truffle/profiler" "^0.1.53" - axios "1.5.0" - axios-retry "^3.7.0" - debug "^4.3.1" - fs-extra "^9.1.0" - iter-tools "^7.0.2" - lodash "^4.17.21" - node-abort-controller "^3.0.1" - original-require "^1.0.1" - require-from-string "^2.0.2" - semver "^7.5.4" - solc "0.8.21" - -"@truffle/compile-vyper@^1.0.33": - version "1.0.71" - resolved "https://registry.yarnpkg.com/@truffle/compile-vyper/-/compile-vyper-1.0.71.tgz#b068fafcf7967c969ece9bb6fd4b505c39c4d1cc" - integrity sha512-p7szaENTOjzCc9LT99gqqqvy1hWJmnul4iRgkStjYOjJIqiNanEDZ715VMisewPK7q/Xa/FYxqTP51XL+ZWKHw== - dependencies: - "@truffle/compile-solidity" "^4.3.22" - colors "^1.1.2" - eslint "^5.5.0" - minimatch "^3.0.4" - -"@truffle/config@^1.2.29", "@truffle/config@^1.2.6", "@truffle/config@^1.3.55": - version "1.3.55" - resolved "https://registry.yarnpkg.com/@truffle/config/-/config-1.3.55.tgz#70ac7103e5a844717303d04deab32ca16356ad83" - integrity sha512-18nLgtnkDCwMiTB3fyJxXzRzuO28wtJyY3YIgJBMg4ujKYpAxeI6hOPafhrp9qGqR7tC0Pj1o+ip3wFxEZJtuQ== - dependencies: - "@truffle/error" "^0.2.0" - "@truffle/events" "^0.1.22" - "@truffle/provider" "^0.3.8" - conf "^10.1.2" - debug "^4.3.1" - find-up "^2.1.0" - lodash "^4.17.21" - original-require "^1.0.1" - -"@truffle/config@^1.3.56": - version "1.3.56" - resolved "https://registry.yarnpkg.com/@truffle/config/-/config-1.3.56.tgz#bb4e9c51fbcfb17117a9d6754b27f3a1491be888" - integrity sha512-2wg6zfaUlP3iZP9jHugx3WsyJ2dbIB+nEBULPK5YVbSkqBfXrzW0b9RJYQvyuk/AyFrp/7ycD4r5LnFLq1IHZA== - dependencies: - "@truffle/error" "^0.2.0" - "@truffle/events" "^0.1.23" - "@truffle/provider" "^0.3.9" - conf "^10.1.2" - debug "^4.3.1" - find-up "^2.1.0" - lodash "^4.17.21" - original-require "^1.0.1" - -"@truffle/config@^1.3.61": - version "1.3.61" - resolved "https://registry.yarnpkg.com/@truffle/config/-/config-1.3.61.tgz#912d11eb03720b6b8cb79979aa56b85215075aec" - integrity sha512-L4uyG47V+k0NrSoVJ9D+hp2jcMstihW1QlNuXiu5g3mU24BjrozlJT34DFkczh/TtRceLjdrQJKA8WJCMICutw== - dependencies: - "@truffle/error" "^0.2.2" - "@truffle/events" "^0.1.25" - "@truffle/provider" "^0.3.13" - conf "^10.1.2" - debug "^4.3.1" - find-up "^2.1.0" - lodash "^4.17.21" - original-require "^1.0.1" - -"@truffle/contract-schema@^3.2.5", "@truffle/contract-schema@^3.3.1", "@truffle/contract-schema@^3.4.11", "@truffle/contract-schema@^3.4.13": - version "3.4.13" - resolved "https://registry.yarnpkg.com/@truffle/contract-schema/-/contract-schema-3.4.13.tgz#48447673f29380830f5821e8139ceefbbd545aac" - integrity sha512-emG7upuryYFrsPDbHqeASPWXL824M1tinhQwSPG0phSoa3g+RX9fUNNN/VPmF3tSkXLWUMhRnb7ehxnaCuRbZg== - dependencies: - ajv "^6.10.0" - debug "^4.3.1" - "@truffle/contract-schema@^3.4.16": version "3.4.16" resolved "https://registry.yarnpkg.com/@truffle/contract-schema/-/contract-schema-3.4.16.tgz#c529c3f230db407b2f03290373b20b7366f2d37e" @@ -5534,74 +4188,10 @@ ajv "^6.10.0" debug "^4.3.1" -"@truffle/contract-sources@^0.1.6", "@truffle/contract-sources@^0.1.8": - version "0.1.12" - resolved "https://registry.yarnpkg.com/@truffle/contract-sources/-/contract-sources-0.1.12.tgz#7a3dfec1bcf6f3632c0f54e522fb6f12b0bdf34b" - integrity sha512-7OH8P+N4n2LewbNiVpuleshPqj8G7n9Qkd5ot79sZ/R6xIRyXF05iBtg3/IbjIzOeQCrCE9aYUHNe2go9RuM0g== - dependencies: - debug "^4.3.1" - glob "^7.1.6" - -"@truffle/contract-sources@^0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@truffle/contract-sources/-/contract-sources-0.2.0.tgz#b8dd1a5e985eb8cf507f23a751aa7aadc0645ab4" - integrity sha512-S14SKQW3EGbLip3rBU7i+VtB5ImBfBz6TpviSXxQsYY6Udy+aqJEmTkVKA/KhHeOG6yQyZqvb4dWIbMtEh+tYg== - dependencies: - debug "^4.3.1" - glob "^7.1.6" - -"@truffle/contract-sources@^0.2.1": - version "0.2.1" - resolved "https://registry.yarnpkg.com/@truffle/contract-sources/-/contract-sources-0.2.1.tgz#ecc043a7f5d72f3428a7205a663aefc376b506c7" - integrity sha512-C7l+lySN2V327s0CAX52mN4h3ag1WpIn6l45hsB92GKhY1t5h5txPUXvuKamQpalQWCTLfMS4+YbtN0AxPxCug== - dependencies: - debug "^4.3.1" - glob "^7.1.6" - -"@truffle/contract@4.6.10": - version "4.6.10" - resolved "https://registry.yarnpkg.com/@truffle/contract/-/contract-4.6.10.tgz#94b2c59273cd142021a6d2fe4de7ac30f572e184" - integrity sha512-69IZSXeQKRP3EutILqe+vLY5A5gUpeXUiZhm/Fy/qHHkP238vMjtOkTZGkY6bonYqmgk+vDY7KSYSYKzDNPdCA== - dependencies: - "@ensdomains/ensjs" "^2.1.0" - "@truffle/blockchain-utils" "^0.1.6" - "@truffle/contract-schema" "^3.4.11" - "@truffle/debug-utils" "^6.0.42" - "@truffle/error" "^0.1.1" - "@truffle/interface-adapter" "^0.5.26" - bignumber.js "^7.2.1" - debug "^4.3.1" - ethers "^4.0.32" - web3 "1.8.1" - web3-core-helpers "1.8.1" - web3-core-promievent "1.8.1" - web3-eth-abi "1.8.1" - web3-utils "1.8.1" - -"@truffle/contract@^4.0.37", "@truffle/contract@^4.2.3", "@truffle/contract@^4.6.10": - version "4.6.20" - resolved "https://registry.yarnpkg.com/@truffle/contract/-/contract-4.6.20.tgz#48237b9d3fe3e5019eac2c8ce9794201ae84fdf8" - integrity sha512-s7Mbc37L/CF5Apy/cjPnalkgACmG9tTAmcIW28cIZLRLOUAze18pqhtdHryxAQhEOtKGaDAho6TriqL7/74uHw== - dependencies: - "@ensdomains/ensjs" "^2.1.0" - "@truffle/blockchain-utils" "^0.1.7" - "@truffle/contract-schema" "^3.4.13" - "@truffle/debug-utils" "^6.0.48" - "@truffle/error" "^0.2.0" - "@truffle/interface-adapter" "^0.5.32" - bignumber.js "^7.2.1" - debug "^4.3.1" - ethers "^4.0.32" - web3 "1.8.2" - web3-core-helpers "1.8.2" - web3-core-promievent "1.8.2" - web3-eth-abi "1.8.2" - web3-utils "1.8.2" - -"@truffle/contract@^4.6.31": - version "4.6.31" - resolved "https://registry.yarnpkg.com/@truffle/contract/-/contract-4.6.31.tgz#75cb059689ce73b365675d9650718908c01b6b58" - integrity sha512-s+oHDpXASnZosiCdzu+X1Tx5mUJUs1L1CYXIcgRmzMghzqJkaUFmR6NpNo7nJYliYbO+O9/aW8oCKqQ7rCHfmQ== +"@truffle/contract@4.6.31": + version "4.6.31" + resolved "https://registry.yarnpkg.com/@truffle/contract/-/contract-4.6.31.tgz#75cb059689ce73b365675d9650718908c01b6b58" + integrity sha512-s+oHDpXASnZosiCdzu+X1Tx5mUJUs1L1CYXIcgRmzMghzqJkaUFmR6NpNo7nJYliYbO+O9/aW8oCKqQ7rCHfmQ== dependencies: "@ensdomains/ensjs" "^2.1.0" "@truffle/blockchain-utils" "^0.1.9" @@ -5618,90 +4208,6 @@ web3-eth-abi "1.10.0" web3-utils "1.10.0" -"@truffle/dashboard-message-bus-client@^0.1.10": - version "0.1.10" - resolved "https://registry.yarnpkg.com/@truffle/dashboard-message-bus-client/-/dashboard-message-bus-client-0.1.10.tgz#bd1cef19956f06716d55a327b8ea6f983e41f0b0" - integrity sha512-r9GpdR96T8xzk2Z3Qq5lowixT6hQwDZ9F3D3oNjOv2AOwBrC7dGkt1Ra1FQRsABn4K7LUVvnjjn6rALlsatAdw== - dependencies: - "@truffle/dashboard-message-bus-common" "^0.1.5" - "@truffle/promise-tracker" "^0.1.5" - axios "1.2.4" - debug "^4.3.1" - delay "^5.0.0" - isomorphic-ws "^4.0.1" - node-abort-controller "^3.0.1" - tiny-typed-emitter "^2.1.0" - ws "^7.2.0" - -"@truffle/dashboard-message-bus-client@^0.1.12": - version "0.1.12" - resolved "https://registry.yarnpkg.com/@truffle/dashboard-message-bus-client/-/dashboard-message-bus-client-0.1.12.tgz#160bf0ae888efee8a45425232d296630f83fe6af" - integrity sha512-pI9G0La9tTstb2J2wxUZIMx6H+ZF0XBlsGN3HBkffr4edT0oT12WMCK9GxmKE22Q5VnpXl7wGjatRSEx0C9qDQ== - dependencies: - "@truffle/dashboard-message-bus-common" "^0.1.7" - "@truffle/promise-tracker" "^0.1.7" - axios "1.5.0" - debug "^4.3.1" - delay "^5.0.0" - isomorphic-ws "^4.0.1" - node-abort-controller "^3.0.1" - tiny-typed-emitter "^2.1.0" - ws "^7.2.0" - -"@truffle/dashboard-message-bus-common@^0.1.5": - version "0.1.5" - resolved "https://registry.yarnpkg.com/@truffle/dashboard-message-bus-common/-/dashboard-message-bus-common-0.1.5.tgz#180c8c421b2836b7bd109944e7956f427236d8ab" - integrity sha512-F4RfXi7ymNA3HFOlaujRJxAb3I8ciErCRQq+MZVaqjSPF9LSw23IizZsGpLaY43K2bGoBSxyNQRZWxsUEBujPQ== - -"@truffle/dashboard-message-bus-common@^0.1.7": - version "0.1.7" - resolved "https://registry.yarnpkg.com/@truffle/dashboard-message-bus-common/-/dashboard-message-bus-common-0.1.7.tgz#dc7b76e18845788429929a97a416c1e6e37580dc" - integrity sha512-jN7q8LBmwQRldSzT/YJE33mnDLrp3EFFDuZyLwtQGInlfcRTXcr5yPY42jxr3Ln19dQe2Chx3I6dWtDByeKLIQ== - -"@truffle/db-loader@^0.2.24": - version "0.2.24" - resolved "https://registry.yarnpkg.com/@truffle/db-loader/-/db-loader-0.2.24.tgz#a8df634755f49e9849374e0160f6a5e5912d0a65" - integrity sha512-ucnZqVb4Aw9fnsUnqwgKZiaDUcw2n6C4tuGyl2iVOr1Xpl+F5Cgrz1cfjJ1igdZrtZnmKl0tDvymt2YwPeeYgw== - optionalDependencies: - "@truffle/db" "^2.0.24" - -"@truffle/db@^2.0.24": - version "2.0.24" - resolved "https://registry.yarnpkg.com/@truffle/db/-/db-2.0.24.tgz#8c603c625b89b60ade0df405f684aba7b851b42c" - integrity sha512-p4UsUKd47/Iv2SJ2m24+ObIalb4Ljt7ysv3mY/gKvEIw3fKxSErPgxDKaC0l3kPOVaz8gfXkbWDGeuLf/f66+Q== - dependencies: - "@graphql-tools/delegate" "^8.4.3" - "@graphql-tools/schema" "^8.3.1" - "@truffle/abi-utils" "^0.3.10" - "@truffle/code-utils" "^3.0.2" - "@truffle/config" "^1.3.56" - abstract-leveldown "^7.2.0" - apollo-server "^3.11.0" - debug "^4.3.1" - fs-extra "^9.1.0" - graphql "^15.3.0" - graphql-tag "^2.12.6" - json-stable-stringify "^1.0.1" - pascal-case "^2.0.1" - pluralize "^8.0.0" - pouchdb "7.3.0" - pouchdb-adapter-memory "^7.1.1" - pouchdb-debug "^7.1.1" - pouchdb-find "^7.0.0" - web3-utils "1.10.0" - -"@truffle/debug-utils@^6.0.42", "@truffle/debug-utils@^6.0.48": - version "6.0.48" - resolved "https://registry.yarnpkg.com/@truffle/debug-utils/-/debug-utils-6.0.48.tgz#218caa0e00d95a03abadb05dfe63d621530e113a" - integrity sha512-HdK/7eH5EFrcTPeZVEgKaKkkzuZ4xsrH8yw+EoLEsScLsOEuQeKynY61NctjuU93voATWrYmV99Sfb/MRq2i2g== - dependencies: - "@truffle/codec" "^0.14.17" - "@trufflesuite/chromafi" "^3.0.0" - bn.js "^5.1.3" - chalk "^2.4.2" - debug "^4.3.1" - highlightjs-solidity "^2.0.6" - "@truffle/debug-utils@^6.0.57": version "6.0.57" resolved "https://registry.yarnpkg.com/@truffle/debug-utils/-/debug-utils-6.0.57.tgz#4e9a1051221c5f467daa398b0ca638d8b6408a82" @@ -5714,139 +4220,11 @@ debug "^4.3.1" highlightjs-solidity "^2.0.6" -"@truffle/debugger@^11.1.0": - version "11.1.0" - resolved "https://registry.yarnpkg.com/@truffle/debugger/-/debugger-11.1.0.tgz#2668b50689c88bd93b8a6e44ef7691a9bd2cc216" - integrity sha512-ws3z3ktvW631W6zi9jd9O6+osF6jh+Z6naumIf9ySfAM1cdV4wTHd8iyYwEEc180pJinlc4oCZGvcr5cE97NVw== - dependencies: - "@ensdomains/ensjs" "^2.1.0" - "@truffle/abi-utils" "^0.3.10" - "@truffle/codec" "^0.15.0" - "@truffle/source-map-utils" "^1.3.111" - bn.js "^5.1.3" - debug "^4.3.1" - json-pointer "^0.6.1" - json-stable-stringify "^1.0.1" - lodash "^4.17.21" - redux "^3.7.2" - redux-saga "1.0.0" - reselect-tree "^1.3.7" - semver "7.3.7" - web3 "1.10.0" - web3-eth-abi "1.10.0" - -"@truffle/error@0.0.7": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@truffle/error/-/error-0.0.7.tgz#e9db39885575647ef08bf624b0c13fe46d41a209" - integrity sha512-UIfVKsXSXocKnn5+RNklUXNoGd/JVj7V8KmC48TQzmjU33HQI86PX0JDS7SpHMHasI3w9X//1q7Lu7nZtj3Zzg== - -"@truffle/error@^0.0.11": - version "0.0.11" - resolved "https://registry.yarnpkg.com/@truffle/error/-/error-0.0.11.tgz#2789c0042d7e796dcbb840c7a9b5d2bcd8e0e2d8" - integrity sha512-ju6TucjlJkfYMmdraYY/IBJaFb+Sa+huhYtOoyOJ+G29KcgytUVnDzKGwC7Kgk6IsxQMm62Mc1E0GZzFbGGipw== - -"@truffle/error@^0.1.1": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@truffle/error/-/error-0.1.1.tgz#e52026ac8ca7180d83443dca73c03e07ace2a301" - integrity sha512-sE7c9IHIGdbK4YayH4BC8i8qMjoAOeg6nUXUDZZp8wlU21/EMpaG+CLx+KqcIPyR+GSWIW3Dm0PXkr2nlggFDA== - -"@truffle/error@^0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@truffle/error/-/error-0.2.0.tgz#65de6f03f5c041f883cc87677eecf8231428f1ab" - integrity sha512-Fe0/z4WWb7IP2gBnv3l6zqP87Y0kSMs7oiSLakKJq17q3GUunrHSdioKuNspdggxkXIBhEQLhi8C+LJdwmHKWQ== - "@truffle/error@^0.2.2": version "0.2.2" resolved "https://registry.yarnpkg.com/@truffle/error/-/error-0.2.2.tgz#1b4c4237c14dda792f20bd4f19ff4e4585b47796" integrity sha512-TqbzJ0O8DHh34cu8gDujnYl4dUl6o2DE4PR6iokbybvnIm/L2xl6+Gv1VC+YJS45xfH83Yo3/Zyg/9Oq8/xZWg== -"@truffle/events@^0.1.22": - version "0.1.22" - resolved "https://registry.yarnpkg.com/@truffle/events/-/events-0.1.22.tgz#007617de4d20093e8c257a63ddc1193a21a9c5b8" - integrity sha512-WBEfaQ5zagS3J1M66J8wQ8N1As/EnBjLQsRlCCFs3/KbmeWhsoalVZ5Effhe0Vxd+e+k7lvwbloQBdS6roc+wg== - dependencies: - "@truffle/dashboard-message-bus-client" "^0.1.10" - "@truffle/spinners" "^0.2.3" - debug "^4.3.1" - emittery "^0.4.1" - web3-utils "1.8.2" - -"@truffle/events@^0.1.23": - version "0.1.23" - resolved "https://registry.yarnpkg.com/@truffle/events/-/events-0.1.23.tgz#26c5824623795724fb1bfbff12753a59c121587e" - integrity sha512-OIcOZXDCJPz9zzK4uTj0HxCqASNKVcs6g3Z9fT6sehGZRD4ubGHpQZoMchLBwXcggoDRApq2svTdghai624pLg== - dependencies: - "@truffle/dashboard-message-bus-client" "^0.1.10" - "@truffle/spinners" "^0.2.3" - debug "^4.3.1" - emittery "^0.4.1" - web3-utils "1.10.0" - -"@truffle/events@^0.1.25": - version "0.1.25" - resolved "https://registry.yarnpkg.com/@truffle/events/-/events-0.1.25.tgz#52d4ae968273c267edfcb5c8e2d3b90c7f1f6b89" - integrity sha512-5elJxNXPVuXDMOoIcCVox0sz95ovRhRbte/H9ht18vyOvtualb4bTjwYyRoWw6Y7j0pom0tPI3OLZWqCdKQNdA== - dependencies: - "@truffle/dashboard-message-bus-client" "^0.1.12" - "@truffle/spinners" "^0.2.5" - debug "^4.3.1" - emittery "^0.4.1" - web3-utils "1.10.0" - -"@truffle/expect@0.0.12": - version "0.0.12" - resolved "https://registry.yarnpkg.com/@truffle/expect/-/expect-0.0.12.tgz#ed609cc538753e79438eb5a9bda7c2fda8ec2535" - integrity sha512-5Hyhrf42wvxCdzv6r8q94lDEQa1onMj6A+/lHTTmirfzqIpk4V32yV22DeFL5QuDFfPaParIT5oHOcQGVAg6XQ== - -"@truffle/expect@^0.0.13": - version "0.0.13" - resolved "https://registry.yarnpkg.com/@truffle/expect/-/expect-0.0.13.tgz#c8e23edc1a1c3b13f768611e6199113026cf8bf2" - integrity sha512-iLRALoFphCCA2ygDjyG+633dCMp81i09+V/oMDkdvDdYDF6KHjSt3Ov9eZMDnzl5PVBvmf2221U4qXSFB8V4fg== - -"@truffle/expect@^0.0.15": - version "0.0.15" - resolved "https://registry.yarnpkg.com/@truffle/expect/-/expect-0.0.15.tgz#293b773680d3e088b8c102480df55907234db533" - integrity sha512-hrIbDRsaEoIkapvY2unw8W5b5qfkz3A3ayxUVxfdPlnevdDUVmvfqfYJrJOSdtbIucwDIhU74VaBPKyiqoTJOw== - -"@truffle/expect@^0.1.4", "@truffle/expect@^0.1.5": - version "0.1.5" - resolved "https://registry.yarnpkg.com/@truffle/expect/-/expect-0.1.5.tgz#9b6d3d8e2f3765d8975506d50cd70a47e71161f7" - integrity sha512-CkrR2BbT2ORwy1l39few03JlXysthXQIjWPk8vC2uA8orcUpMv7PWC4AoVbTvE2OgcnbClpYekGFyaQ9iToyAg== - -"@truffle/expect@^0.1.7": - version "0.1.7" - resolved "https://registry.yarnpkg.com/@truffle/expect/-/expect-0.1.7.tgz#290e7822239355f8ec95e4cdf93f171818ddfd1f" - integrity sha512-YWLdtIDA2Xl7RdkmurQw2KCV/b59KJJ2Csm4GYNPAsnngvVOH6qvHjqm1JNyDzBN7AzqT+Tb3s8RdD+EZC3HJw== - -"@truffle/external-compile@^1.0.19": - version "1.0.36" - resolved "https://registry.yarnpkg.com/@truffle/external-compile/-/external-compile-1.0.36.tgz#92b9a7e427e11c930159ac130028a565ad2df5d4" - integrity sha512-01qd3lHCrk+mA6D93YP3dguFmYjehToz5VQgiYRwf2d7XzH7iXlRRk2rqG3PUGx5awgAJFsyGIwqGyy04NXVfw== - dependencies: - "@truffle/contract-schema" "^3.2.5" - "@truffle/expect" "^0.0.15" - debug "^4.1.0" - glob "^7.1.2" - web3-utils "1.2.1" - -"@truffle/interface-adapter@^0.5.26", "@truffle/interface-adapter@^0.5.32": - version "0.5.32" - resolved "https://registry.yarnpkg.com/@truffle/interface-adapter/-/interface-adapter-0.5.32.tgz#2ae896ea85a9d267abcd5d0139afc0f06ebc5745" - integrity sha512-7Hgmdb4nJUcWtq4vvgWY7Mr2RLOTOp5FZaWyMiFmjkcEEhDlezm2QstALWAXgT0W6q7tDmDBpw3vTIFenRhHBA== - dependencies: - bn.js "^5.1.3" - ethers "^4.0.32" - web3 "1.8.2" - -"@truffle/interface-adapter@^0.5.33": - version "0.5.33" - resolved "https://registry.yarnpkg.com/@truffle/interface-adapter/-/interface-adapter-0.5.33.tgz#249c9a378a91e12c5e5e0657b419596a43caa088" - integrity sha512-vbVcH2I8hX+wM0Xj9uAjpgxMHqfT+y6m26zSkOVvZ2wo9Ez1slaOJkK1/TZK+7nJitGZSXeJeB4purMDuADvGA== - dependencies: - bn.js "^5.1.3" - ethers "^4.0.32" - web3 "1.10.0" - "@truffle/interface-adapter@^0.5.37": version "0.5.37" resolved "https://registry.yarnpkg.com/@truffle/interface-adapter/-/interface-adapter-0.5.37.tgz#95d249c1912d2baaa63c54e8a138d3f476a1181a" @@ -5856,157 +4234,6 @@ ethers "^4.0.32" web3 "1.10.0" -"@truffle/profiler@^0.1.47": - version "0.1.47" - resolved "https://registry.yarnpkg.com/@truffle/profiler/-/profiler-0.1.47.tgz#fee15be5ff2131115762f973228d64d960862f3c" - integrity sha512-CMX6TzlrFFpRb8RoHmlICRbusFPp0F8u0d1GaC2TW1tvfe5Ug4oLjAh5dBGpENDbm9DpMrbHV/2YvAyJzSYa1w== - dependencies: - "@truffle/contract-sources" "^0.2.0" - "@truffle/expect" "^0.1.5" - debug "^4.3.1" - -"@truffle/profiler@^0.1.53": - version "0.1.53" - resolved "https://registry.yarnpkg.com/@truffle/profiler/-/profiler-0.1.53.tgz#7be1d8f11d774738a34d0f41f26956a4eaa7fd92" - integrity sha512-3+wfDaa0JdHlZpjJaNjgsi6vJfeq4osPz146uNYhDH5ilnDGAG1OMrjnuCbkpG3/oXycKsUZFMnVtkbCbbaISw== - dependencies: - "@truffle/contract-sources" "^0.2.1" - "@truffle/expect" "^0.1.7" - debug "^4.3.1" - -"@truffle/promise-tracker@^0.1.5": - version "0.1.5" - resolved "https://registry.yarnpkg.com/@truffle/promise-tracker/-/promise-tracker-0.1.5.tgz#df68df14d45a32bda6237ab85169d1808e4b3928" - integrity sha512-wZx8eeu/6rcwwkmRF0Y832/NSQR9A9u6pyhTozv+j77jklnd/KZvu2JlACaAjP30eL5SOtSrSOzAMcSh/trJjg== - -"@truffle/promise-tracker@^0.1.7": - version "0.1.7" - resolved "https://registry.yarnpkg.com/@truffle/promise-tracker/-/promise-tracker-0.1.7.tgz#edc5e5940656439db7b1956bd4838d12dd4b9ecf" - integrity sha512-NiPXNJvdei8MRZRUjEZoL0Y7TPDR1TaeCfGUgB3md6Q7TBiqSKo2p5OT36JO106B2j57SLmXOiDn8fLb+u2sjA== - -"@truffle/provider@^0.3.13": - version "0.3.13" - resolved "https://registry.yarnpkg.com/@truffle/provider/-/provider-0.3.13.tgz#795b6172c5db20f30a026f2f733b9a3417847a9f" - integrity sha512-W9yZO0ZUwA0LhFvf7+NNNXVSCOd4x5pTbFiXUVURjyqp7f4YooLAqnlLPSpV+6qwIwThc+86CeLlOiFslYdDIA== - dependencies: - "@truffle/error" "^0.2.2" - "@truffle/interface-adapter" "^0.5.37" - debug "^4.3.1" - web3 "1.10.0" - -"@truffle/provider@^0.3.8": - version "0.3.8" - resolved "https://registry.yarnpkg.com/@truffle/provider/-/provider-0.3.8.tgz#8b34d17edf701226c8fab05e34cd6b09742c4041" - integrity sha512-qukkmGOZPsbV7WeKlj/bfYWOu/dbHWlF67QHDhV2KHBVardN06VDf40aB8WeeVkONHijb623hkUI/DE4DpHO+Q== - dependencies: - "@truffle/error" "^0.2.0" - "@truffle/interface-adapter" "^0.5.32" - debug "^4.3.1" - web3 "1.8.2" - -"@truffle/provider@^0.3.9": - version "0.3.9" - resolved "https://registry.yarnpkg.com/@truffle/provider/-/provider-0.3.9.tgz#d1e66dbeaa743ba4d3e67911f722f841fbd81d0b" - integrity sha512-6vVSpbP8b2SuNz1fE1KeeQHMBaQ7oD5Nf4CLikXNWrj3SVyMpN3PxsEnaHMnlslAfHICpLSOHpcIWETGxfOgbg== - dependencies: - "@truffle/error" "^0.2.0" - "@truffle/interface-adapter" "^0.5.33" - debug "^4.3.1" - web3 "1.10.0" - -"@truffle/provisioner@^0.2.0", "@truffle/provisioner@^0.2.70": - version "0.2.78" - resolved "https://registry.yarnpkg.com/@truffle/provisioner/-/provisioner-0.2.78.tgz#4aad0b8b911bd5a182637504e9b629015150b1eb" - integrity sha512-DFT3n6oXIsvTRwg4/f5RA+iyQB8ivQTyo44JkgUecBgpX1tQ20wRgbfww/018kkeKVix4n9J/CzRJvv3YOve/w== - dependencies: - "@truffle/config" "^1.3.55" - -"@truffle/provisioner@^0.2.84": - version "0.2.84" - resolved "https://registry.yarnpkg.com/@truffle/provisioner/-/provisioner-0.2.84.tgz#ee464dec1299a7c6230e335d5cb3a0ef7469d22a" - integrity sha512-zgDeSq+ZAcgtKSDlShtn1bsJWTRgeOdTTVzthjXMJisKnRQChkOAp7ehIr0RoIp5o2T1IVxYILAk7IPYDHNzuQ== - dependencies: - "@truffle/config" "^1.3.61" - -"@truffle/resolver@9.0.27": - version "9.0.27" - resolved "https://registry.yarnpkg.com/@truffle/resolver/-/resolver-9.0.27.tgz#7c0eaa1cb30ada2951cde44f537baa53fce4c49c" - integrity sha512-sNYMXqyEEtKAp2zkT+NQJ5pTXa41aEUF3HuLi2Sqt+bBKT8RjQoqM7PwNO0DzoLIwmRba8mpLoNMq87ALb8N5Q== - dependencies: - "@ganache/console.log" "0.2.0" - "@truffle/compile-solidity" "^6.0.54" - "@truffle/contract" "^4.6.10" - "@truffle/contract-sources" "^0.2.0" - "@truffle/expect" "^0.1.4" - "@truffle/provisioner" "^0.2.70" - abi-to-sol "^0.6.6" - debug "^4.3.1" - detect-installed "^2.0.4" - fs-extra "^9.1.0" - get-installed-path "^4.0.8" - glob "^7.1.6" - web3-utils "1.8.1" - -"@truffle/resolver@^5.0.18": - version "5.1.12" - resolved "https://registry.yarnpkg.com/@truffle/resolver/-/resolver-5.1.12.tgz#69c220973bb3326c3513a8e3e5a524f3aaa30f62" - integrity sha512-xiv7okPFT9mUZ9kc4iNMVPE85bGDdDwpMYE/LTmcpLNechmXlphgc3DzwJdQypZd6NjCrc/C1XMF178UiS+Szg== - dependencies: - "@truffle/contract" "^4.2.3" - "@truffle/expect" "^0.0.13" - "@truffle/provisioner" "^0.2.0" - debug "^4.1.1" - detect-installed "^2.0.4" - get-installed-path "^4.0.8" - glob "^7.1.6" - source-map-support "^0.5.16" - supports-color "^7.1.0" - -"@truffle/resolver@^9.0.35": - version "9.0.53" - resolved "https://registry.yarnpkg.com/@truffle/resolver/-/resolver-9.0.53.tgz#1864463c17b4aa54136ae015a40d19d15a33c97b" - integrity sha512-jYqHIucs6yMCOpKFwnvcW6cfpn/WEWJQ8FN0EUhf0r0HMz9TjG9HnabBZSvfMBFPAmKklGR/GI0GESWf3alpXQ== - dependencies: - "@ganache/console.log" "0.3.0" - "@truffle/compile-solidity" "^6.0.79" - "@truffle/contract" "^4.6.31" - "@truffle/contract-sources" "^0.2.1" - "@truffle/expect" "^0.1.7" - "@truffle/provisioner" "^0.2.84" - abi-to-sol "^0.7.0" - debug "^4.3.1" - detect-installed "^2.0.4" - fs-extra "^9.1.0" - get-installed-path "^4.0.8" - glob "^7.1.6" - web3-utils "1.10.0" - -"@truffle/source-map-utils@^1.3.111": - version "1.3.111" - resolved "https://registry.yarnpkg.com/@truffle/source-map-utils/-/source-map-utils-1.3.111.tgz#8ebc52f6a7f7f77f4ff302141c11e09dd7f8a220" - integrity sha512-/2kP4muycNMvMwar/QuzRdF8NE8LpQS1cRHF43XLx3b89D/upzqTylQwv3EDx/rcd7u6AQ/7lrUSmKlh0+k40Q== - dependencies: - "@truffle/code-utils" "^3.0.2" - "@truffle/codec" "^0.15.0" - debug "^4.3.1" - json-pointer "^0.6.1" - node-interval-tree "^1.3.3" - web3-utils "1.10.0" - -"@truffle/spinners@^0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@truffle/spinners/-/spinners-0.2.3.tgz#5689d06ef16855a9f6b70dc0cd40188de54450ec" - integrity sha512-YnaQ+oBRQ1I1+/P18i8oSW4orUYi6vwpZQxauEZ5X0L8atjKq+RWdiNaza6J6L+KOLunXM4+pWxnNzuUmxlJZw== - dependencies: - "@trufflesuite/spinnies" "^0.1.1" - -"@truffle/spinners@^0.2.5": - version "0.2.5" - resolved "https://registry.yarnpkg.com/@truffle/spinners/-/spinners-0.2.5.tgz#fe3bb3451768f5353085551b8fe6285d354705ef" - integrity sha512-emYyLEuoY62MQV/RNjyVIuTPEjMyIA0WiYMG2N3yfh8OSjD/TC0HRc2oyDWtVkNNox/5D2tH2m5fFB8HOt80FQ== - dependencies: - "@trufflesuite/spinnies" "^0.1.1" - "@trufflesuite/bigint-buffer@1.1.10": version "1.1.10" resolved "https://registry.yarnpkg.com/@trufflesuite/bigint-buffer/-/bigint-buffer-1.1.10.tgz#a1d9ca22d3cad1a138b78baaf15543637a3e1692" @@ -6014,13 +4241,6 @@ dependencies: node-gyp-build "4.4.0" -"@trufflesuite/bigint-buffer@1.1.9": - version "1.1.9" - resolved "https://registry.yarnpkg.com/@trufflesuite/bigint-buffer/-/bigint-buffer-1.1.9.tgz#e2604d76e1e4747b74376d68f1312f9944d0d75d" - integrity sha512-bdM5cEGCOhDSwminryHJbRmXc1x7dPKg6Pqns3qyTwFlxsqUgxE29lsERS3PlIW1HTjoIGMUqsk1zQQwST1Yxw== - dependencies: - node-gyp-build "4.3.0" - "@trufflesuite/chromafi@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@trufflesuite/chromafi/-/chromafi-3.0.0.tgz#f6956408c1af6a38a6ed1657783ce59504a1eb8b" @@ -6035,15 +4255,6 @@ strip-ansi "^4.0.0" strip-indent "^2.0.0" -"@trufflesuite/spinnies@^0.1.1": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@trufflesuite/spinnies/-/spinnies-0.1.1.tgz#719230993f55ab39f936ed8778979e7661af188d" - integrity sha512-jltEtmFJj6xmQqr85gP8OqBHCEiId+zw+uAsb3DyLLRD17O6sySW6Afa2Z/jpzSafj+32ssDfLJ+c0of1NLqcA== - dependencies: - chalk "^4.1.2" - cli-cursor "^3.1.0" - strip-ansi "^6.0.0" - "@trufflesuite/uws-js-unofficial@20.10.0-unofficial.2": version "20.10.0-unofficial.2" resolved "https://registry.yarnpkg.com/@trufflesuite/uws-js-unofficial/-/uws-js-unofficial-20.10.0-unofficial.2.tgz#7ed613ce3260cd5d1773a4d5787a2a106acd1a91" @@ -6074,11 +4285,6 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== -"@types/abstract-leveldown@*": - version "7.2.1" - resolved "https://registry.yarnpkg.com/@types/abstract-leveldown/-/abstract-leveldown-7.2.1.tgz#bb16403c17754b0c4d5772d71d03b924a03d4c80" - integrity sha512-YK8irIC+eMrrmtGx0H4ISn9GgzLd9dojZWJaMbjp1YHLl2VqqNFBNrL5Q3KjGf4VE3sf/4hmq6EhQZ7kZp1NoQ== - "@types/accepts@*": version "1.3.6" resolved "https://registry.yarnpkg.com/@types/accepts/-/accepts-1.3.6.tgz#5e33830c8ed7b6025976738c88540df2e85b6d91" @@ -6086,13 +4292,6 @@ dependencies: "@types/node" "*" -"@types/accepts@^1.3.5": - version "1.3.5" - resolved "https://registry.yarnpkg.com/@types/accepts/-/accepts-1.3.5.tgz#c34bec115cfc746e04fe5a059df4ce7e7b391575" - integrity sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ== - dependencies: - "@types/node" "*" - "@types/asn1js@^0.0.2": version "0.0.2" resolved "https://registry.yarnpkg.com/@types/asn1js/-/asn1js-0.0.2.tgz#f278a8af81861813d4fc9cd0a86c8b1ac5f16db3" @@ -6138,14 +4337,14 @@ dependencies: "@babel/types" "^7.3.0" -"@types/bn.js@*", "@types/bn.js@4.11.6", "@types/bn.js@^4.11.0", "@types/bn.js@^4.11.3", "@types/bn.js@^4.11.4", "@types/bn.js@^5.1.0", "@types/bn.js@^5.1.1": +"@types/bn.js@*", "@types/bn.js@4.11.6", "@types/bn.js@^5.1.0", "@types/bn.js@^5.1.1": version "4.11.6" resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== dependencies: "@types/node" "*" -"@types/body-parser@*", "@types/body-parser@1.19.2": +"@types/body-parser@*": version "1.19.2" resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== @@ -6160,13 +4359,6 @@ dependencies: "@types/node" "*" -"@types/bunyan@1.8.8": - version "1.8.8" - resolved "https://registry.yarnpkg.com/@types/bunyan/-/bunyan-1.8.8.tgz#8d6d33f090f37c07e2a80af30ae728450a101008" - integrity sha512-Cblq+Yydg3u+sGiz2mjHjC5MPmdjY+No4qvHrF+BUhblsmSfMvsHLbOG62tPbonsqBj6sbWv1LHcsoe5Jw+/Ow== - dependencies: - "@types/node" "*" - "@types/bunyan@1.8.9": version "1.8.9" resolved "https://registry.yarnpkg.com/@types/bunyan/-/bunyan-1.8.9.tgz#22d4517f3217b7c8f5a69bbc8c9f6df79779dcb5" @@ -6174,14 +4366,6 @@ dependencies: "@types/node" "*" -"@types/bytebuffer@^5.0.40": - version "5.0.44" - resolved "https://registry.yarnpkg.com/@types/bytebuffer/-/bytebuffer-5.0.44.tgz#553015fb34db1fc3eb3f7b232bff91c006c251a1" - integrity sha512-k1qonHga/SfQT02NF633i+7tIfKd+cfC/8pjnedcfuXJNMWooss/FkCgRMSnLf2WorLjbuH4bfgAZEbtyHBDoQ== - dependencies: - "@types/long" "^3.0.0" - "@types/node" "*" - "@types/cacheable-request@^6.0.1", "@types/cacheable-request@^6.0.2": version "6.0.3" resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz#a430b3260466ca7b5ca5bfd735693b36e7a9d183" @@ -6192,30 +4376,6 @@ "@types/node" "*" "@types/responselike" "^1.0.0" -"@types/caseless@*": - version "0.12.2" - resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.2.tgz#f65d3d6389e01eeb458bd54dc8f52b95a9463bc8" - integrity sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w== - -"@types/cbor@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/cbor/-/cbor-2.0.0.tgz#c627afc2ee22f23f2337fecb34628a4f97c6afbb" - integrity sha512-yQH0JLcrHrH/GBIFFFq6DAsj9M4rmYsmSpGGGs67JrLGWPepYr2c1YugGjMd2Ib5pebluRAfNPJ4O1p80qX9HQ== - dependencies: - "@types/node" "*" - -"@types/chai-subset@1.3.3": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@types/chai-subset/-/chai-subset-1.3.3.tgz#97893814e92abd2c534de422cb377e0e0bdaac94" - integrity sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw== - dependencies: - "@types/chai" "*" - -"@types/chai@*", "@types/chai@^4.1.3", "@types/chai@^4.1.4": - version "4.3.4" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.4.tgz#e913e8175db8307d78b4e8fa690408ba6b65dee4" - integrity sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw== - "@types/cli-table@^0.3.0": version "0.3.1" resolved "https://registry.yarnpkg.com/@types/cli-table/-/cli-table-0.3.1.tgz#a0ae06290284f7abebb90a2ddc0187de6d22e963" @@ -6226,13 +4386,6 @@ resolved "https://registry.yarnpkg.com/@types/command-exists/-/command-exists-1.2.0.tgz#d97e0ed10097090e4ab0367ed425b0312fad86f3" integrity sha512-ugsxEJfsCuqMLSuCD4PIJkp5Uk2z6TCMRCgYVuhRo5cYQY3+1xXTQkSlPtkpGHuvWMjS2KTeVQXxkXRACMbM6A== -"@types/concat-stream@^1.6.0": - version "1.6.1" - resolved "https://registry.yarnpkg.com/@types/concat-stream/-/concat-stream-1.6.1.tgz#24bcfc101ecf68e886aaedce60dfd74b632a1b74" - integrity sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA== - dependencies: - "@types/node" "*" - "@types/connect@*": version "3.4.35" resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" @@ -6262,11 +4415,6 @@ "@types/keygrip" "*" "@types/node" "*" -"@types/cors@2.8.12": - version "2.8.12" - resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080" - integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw== - "@types/country-data@^0.0.0": version "0.0.0" resolved "https://registry.yarnpkg.com/@types/country-data/-/country-data-0.0.0.tgz#6f5563cae3d148780c5b6539803a29bd93f8f1a1" @@ -6286,20 +4434,6 @@ dependencies: "@types/ms" "*" -"@types/dotenv@^8.2.0": - version "8.2.0" - resolved "https://registry.yarnpkg.com/@types/dotenv/-/dotenv-8.2.0.tgz#5cd64710c3c98e82d9d15844375a33bf1b45d053" - integrity sha512-ylSC9GhfRH7m1EUXBXofhgx4lUWmFeQDINW5oLuS+gxWdfUeW4zJdeVTYVkexEW+e2VUvlZR2kGnGGipAWR7kw== - dependencies: - dotenv "*" - -"@types/duplexify@^3.6.0": - version "3.6.1" - resolved "https://registry.yarnpkg.com/@types/duplexify/-/duplexify-3.6.1.tgz#5685721cf7dc4a21b6f0e8a8efbec6b4d2fbafad" - integrity sha512-n0zoEj/fMdMOvqbHxmqnza/kXyoGgJmEpsXjpP+gEqE1Ye4yNqc7xWipKnUoMpWhMuzJQSfK2gMrwlElly7OGQ== - dependencies: - "@types/node" "*" - "@types/elliptic@^6.4.9": version "6.4.14" resolved "https://registry.yarnpkg.com/@types/elliptic/-/elliptic-6.4.14.tgz#7bbaad60567a588c1f08b10893453e6b9b4de48e" @@ -6307,32 +4441,6 @@ dependencies: "@types/bn.js" "*" -"@types/ethereum-protocol@*": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@types/ethereum-protocol/-/ethereum-protocol-1.0.2.tgz#e765d4c6f4b5ebe906932bd20333e307c56a9bc7" - integrity sha512-Ri/hwt4UckZlF7eqhhAQcXsNvcgQmSJOKZteLco1/5NsRcneW/cJuQcrQNILN2Ohs9WUQjeGW3ZRRNqkEVMzuQ== - dependencies: - bignumber.js "7.2.1" - -"@types/express-serve-static-core@4.17.31": - version "4.17.31" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.31.tgz#a1139efeab4e7323834bb0226e62ac019f474b2f" - integrity sha512-DxMhY+NAsTwMMFHBTtJFNp5qiHKJ7TeqOo23zVEM9alT1Ml27Q3xcTH0xwxn7Q0BbMcVEJOs/7aQtUWupUQN3Q== - dependencies: - "@types/node" "*" - "@types/qs" "*" - "@types/range-parser" "*" - -"@types/express-serve-static-core@^4.17.18": - version "4.17.35" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz#c95dd4424f0d32e525d23812aa8ab8e4d3906c4f" - integrity sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg== - dependencies: - "@types/node" "*" - "@types/qs" "*" - "@types/range-parser" "*" - "@types/send" "*" - "@types/express-serve-static-core@^4.17.33": version "4.17.33" resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.33.tgz#de35d30a9d637dc1450ad18dd583d75d5733d543" @@ -6352,16 +4460,6 @@ "@types/qs" "*" "@types/serve-static" "*" -"@types/express@4.17.14": - version "4.17.14" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.14.tgz#143ea0557249bc1b3b54f15db4c81c3d4eb3569c" - integrity sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg== - dependencies: - "@types/body-parser" "*" - "@types/express-serve-static-core" "^4.17.18" - "@types/qs" "*" - "@types/serve-static" "*" - "@types/express@4.17.18": version "4.17.18" resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.18.tgz#efabf5c4495c1880df1bdffee604b143b29c4a95" @@ -6377,14 +4475,7 @@ resolved "https://registry.yarnpkg.com/@types/fetch-mock/-/fetch-mock-7.3.5.tgz#7aee678c4e7c7e1a168bae8fdab5b8d712e377f6" integrity sha512-sLecm9ohBdGIpYUP9rWk5/XIKY2xHMYTBJIcJuBBM8IJWnYoQ1DAj8F4OVjnfD0API1drlkWEV0LPNk+ACuhsg== -"@types/form-data@0.0.33": - version "0.0.33" - resolved "https://registry.yarnpkg.com/@types/form-data/-/form-data-0.0.33.tgz#c9ac85b2a5fd18435b8c85d9ecb50e6d6c893ff8" - integrity sha512-8BSvG1kGm83cyJITQMZSulnl6QV8jqAGreJsc5tPu1Jq0vTSOiY/k24Wx82JRpWwZSqrala6sd5rWi6aNXvqcw== - dependencies: - "@types/node" "*" - -"@types/fs-extra@^8.0.0", "@types/fs-extra@^8.1.0": +"@types/fs-extra@^8.0.0": version "8.1.2" resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-8.1.2.tgz#7125cc2e4bdd9bd2fc83005ffdb1d0ba00cca61f" integrity sha512-SvSrYXfWSc7R4eqnOzbQF4TZmfpNSM9FrSWLU3EUnWBuyZqNBOrv1B1JA3byUDPUl9z4Ab3jeZG2eDdySlgNMg== @@ -6452,13 +4543,6 @@ dependencies: "@types/node" "*" -"@types/hdkey@^0.7.0": - version "0.7.1" - resolved "https://registry.yarnpkg.com/@types/hdkey/-/hdkey-0.7.1.tgz#9bc63ebbe96b107b277b65ea7a95442a677d0d61" - integrity sha512-4Kkr06hq+R8a9EzVNqXGOY2x1xA7dhY6qlp6OvaZ+IJy1BCca1Cv126RD9X7CMJoXoLo8WvAizy8gQHpqW6K0Q== - dependencies: - "@types/node" "*" - "@types/http-assert@*": version "1.5.4" resolved "https://registry.yarnpkg.com/@types/http-assert/-/http-assert-1.5.4.tgz#2ee41bf930d871a76cdbee5c385ccbb3604302e6" @@ -6501,11 +4585,6 @@ dependencies: ci-info "^3.1.0" -"@types/isomorphic-fetch@0.0.31": - version "0.0.31" - resolved "https://registry.yarnpkg.com/@types/isomorphic-fetch/-/isomorphic-fetch-0.0.31.tgz#ec120166ce22f0b134e8770f40c97cd076068fae" - integrity sha512-mJLpWAOSe9LmccuMkgL2wMfqTFt4kW5kEw2PhhnDT+J0AUn6e1c7dq5CJKL+iUmc9N1QrgWrah8kWqePpmemKA== - "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": version "2.0.4" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" @@ -6608,24 +4687,6 @@ dependencies: "@types/node" "*" -"@types/levelup@^3.1.1": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@types/levelup/-/levelup-3.1.1.tgz#f7cc08f248f14cb6c92914e91bceb8761020e8f0" - integrity sha512-LjvlfctJYj23Xuqq3jCT8ZPSUSSgDcRJg8+XFDBasoYzefFbB4cHzlDmBVjc2rBOYvklpYHJRayD0jBsbJLD9w== - dependencies: - "@types/abstract-leveldown" "*" - "@types/node" "*" - -"@types/lodash@^4.14.199": - version "4.14.200" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.200.tgz#435b6035c7eba9cdf1e039af8212c9e9281e7149" - integrity sha512-YI/M/4HRImtNf3pJgbF+W6FrXovqj+T+/HpENLTooK9PnkacBsDpeP3IpHab40CClUfhNmdM2WTNP2sa2dni5Q== - -"@types/long@^3.0.0": - version "3.0.32" - resolved "https://registry.yarnpkg.com/@types/long/-/long-3.0.32.tgz#f4e5af31e9e9b196d8e5fca8a5e2e20aa3d60b69" - integrity sha512-ZXyOOm83p7X8p3s0IYM3VeueNmHpkk/yMlP8CLeOnEcu6hIwPH7YjZBvhQkR0ZFS2DqZAxKtJ/M5fcuv3OU5BA== - "@types/long@^4.0.0", "@types/long@^4.0.1": version "4.0.2" resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a" @@ -6636,13 +4697,6 @@ resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef" integrity sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw== -"@types/mathjs@^4.4.1": - version "4.4.5" - resolved "https://registry.yarnpkg.com/@types/mathjs/-/mathjs-4.4.5.tgz#b28d46919c68b93bcabf0551729624b302af9b4b" - integrity sha512-Z9XyD6ORkE/dTwCGQ4htXaB8D/OkcRhQy4EtEvJ6lRmbgcYoS2q3CAMoB3s2mgQZmyQy85gtJcfbCz85LV1w+Q== - dependencies: - decimal.js "^10.0.0" - "@types/memcached@^2.2.6": version "2.2.9" resolved "https://registry.yarnpkg.com/@types/memcached/-/memcached-2.2.9.tgz#dba55dadbd442573d5a12f1cd2cdd6bd64d86537" @@ -6660,11 +4714,6 @@ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10" integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA== -"@types/mime@^1": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" - integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== - "@types/minimatch@*", "@types/minimatch@^5.1.2": version "5.1.2" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" @@ -6680,23 +4729,6 @@ resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c" integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ== -"@types/mkdirp@^0.5.2": - version "0.5.2" - resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-0.5.2.tgz#503aacfe5cc2703d5484326b1b27efa67a339c1f" - integrity sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg== - dependencies: - "@types/node" "*" - -"@types/mocha@^10.0.1": - version "10.0.1" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.1.tgz#2f4f65bb08bc368ac39c96da7b2f09140b26851b" - integrity sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q== - -"@types/mocha@^5.2.5", "@types/mocha@^5.2.7": - version "5.2.7" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.7.tgz#315d570ccb56c53452ff8638738df60726d5b6ea" - integrity sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ== - "@types/mocha@^7.0.2": version "7.0.2" resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-7.0.2.tgz#b17f16cf933597e10d6d78eae3251e692ce8b0ce" @@ -6714,14 +4746,6 @@ dependencies: "@types/node" "*" -"@types/node-fetch@^2.5.7": - version "2.6.3" - resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.3.tgz#175d977f5e24d93ad0f57602693c435c57ad7e80" - integrity sha512-ETTL1mOEdq/sxUtgtOhKjyB2Irra4cjxksvcMUR5Zr4n+PxVhsCD9WS46oPbHL3et9Zde7CNRr+WUNlcHvsX+w== - dependencies: - "@types/node" "*" - form-data "^3.0.0" - "@types/node-hid@*": version "1.3.1" resolved "https://registry.yarnpkg.com/@types/node-hid/-/node-hid-1.3.1.tgz#e84507a35a6f3ece3f6324c21ba9252405758b65" @@ -6739,46 +4763,21 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-11.11.6.tgz#df929d1bb2eee5afdda598a41930fe50b43eaa6a" integrity sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ== -"@types/node@12.12.54": - version "12.12.54" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.54.tgz#a4b58d8df3a4677b6c08bfbc94b7ad7a7a5f82d1" - integrity sha512-ge4xZ3vSBornVYlDnk7yZ0gK6ChHf/CHB7Gl1I0Jhah8DDnEQqBzgohYG4FX4p81TNirSETOiSyn+y1r9/IR6w== - "@types/node@18.7.16": version "18.7.16" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.16.tgz#0eb3cce1e37c79619943d2fd903919fc30850601" integrity sha512-EQHhixfu+mkqHMZl1R2Ovuvn47PUw18azMJOTwSZr9/fhzHNGXAJ0ma0dayRVchprpCj0Kc1K1xKoWaATWF1qg== -"@types/node@^10.0.3", "@types/node@^10.1.0", "@types/node@^10.12.18", "@types/node@^10.3.2": - version "10.17.60" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b" - integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw== - -"@types/node@^12.12.6", "@types/node@^12.6.1", "@types/node@^12.7.1": +"@types/node@^12.12.6", "@types/node@^12.7.1": version "12.20.55" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== -"@types/node@^6.0.52": - version "6.14.13" - resolved "https://registry.yarnpkg.com/@types/node/-/node-6.14.13.tgz#b6649578fc0b5dac88c4ef48a46cab33c50a6c72" - integrity sha512-J1F0XJ/9zxlZel5ZlbeSuHW2OpabrUAqpFuC2sm2I3by8sERQ8+KCjNKUcq8QHuzpGMWiJpo9ZxeHrqrP2KzQw== - -"@types/node@^8.0.0": - version "8.10.66" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.66.tgz#dd035d409df322acc83dff62a602f12a5783bbb3" - integrity sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw== - "@types/normalize-package-data@^2.4.0": version "2.4.1" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw== -"@types/p-defer@^1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@types/p-defer/-/p-defer-1.0.3.tgz#786ce79c86f779fcd9e9bec4f1fbd1167aeac064" - integrity sha512-0CK39nXek0mSZL/lnGYjhcR1QLAxg9N0/5S1BvU+MQwjlP4Jd2ebbEkJ/bEUqYMAvKLMZcGd4sJE13dnUKlDnQ== - "@types/parse-json@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" @@ -6816,25 +4815,6 @@ pg-protocol "*" pg-types "^2.2.0" -"@types/pg@^7.14.3": - version "7.14.11" - resolved "https://registry.yarnpkg.com/@types/pg/-/pg-7.14.11.tgz#daf5555504a1f7af4263df265d91f140fece52e3" - integrity sha512-EnZkZ1OMw9DvNfQkn2MTJrwKmhJYDEs5ujWrPfvseWNoI95N8B4HzU/Ltrq5ZfYxDX/Zg8mTzwr6UAyTjjFvXA== - dependencies: - "@types/node" "*" - pg-protocol "^1.2.0" - pg-types "^2.2.0" - -"@types/prettier@^1.13.2": - version "1.19.1" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-1.19.1.tgz#33509849f8e679e4add158959fdb086440e9553f" - integrity sha512-5qOlnZscTn4xxM5MeGXAMOsIOIKIbh9e85zJWfBRVPlRMEVawzoPhINYbRGkBZCI8LxvBe7tJCdWiarA99OZfQ== - -"@types/prettier@^2.1.1": - version "2.7.3" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.3.tgz#3e51a17e291d01d17d3fc61422015a933af7a08f" - integrity sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA== - "@types/prettier@^2.1.5": version "2.7.2" resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.2.tgz#6c2324641cc4ba050a8c710b2b251b377581fbf0" @@ -6853,11 +4833,6 @@ resolved "https://registry.yarnpkg.com/@types/prompts/-/prompts-1.2.0.tgz#891e73f735ad5e82e8adae3a99424128e105fb62" integrity sha512-7JXpT2rSd4hqd2oBWU1wfEW6x6gX+qPH+gLzGEx+My3wcb67K9Rc02xNQRVn67phusmXm5Yqn4oTP2OW1G5zdQ== -"@types/prop-types@*": - version "15.7.5" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" - integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== - "@types/pvutils@*": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/pvutils/-/pvutils-1.0.1.tgz#f23c5c7915faedf4d281226579cf361127adea11" @@ -6870,7 +4845,7 @@ dependencies: "@types/node" "*" -"@types/qs@*", "@types/qs@^6.2.31": +"@types/qs@*": version "6.9.7" resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== @@ -6887,44 +4862,10 @@ resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== -"@types/react@*": - version "18.0.38" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.38.tgz#02a23bef8848b360a0d1dceef4432c15c21c600c" - integrity sha512-ExsidLLSzYj4cvaQjGnQCk4HFfVT9+EZ9XZsQ8Hsrcn8QNgXtpZ3m9vSIC2MWtx7jHictK6wYhQgGh6ic58oOw== - dependencies: - "@types/prop-types" "*" - "@types/scheduler" "*" - csstype "^3.0.2" - -"@types/readable-stream@^2.3.13": - version "2.3.15" - resolved "https://registry.yarnpkg.com/@types/readable-stream/-/readable-stream-2.3.15.tgz#3d79c9ceb1b6a57d5f6e6976f489b9b5384321ae" - integrity sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ== - dependencies: - "@types/node" "*" - safe-buffer "~5.1.1" - -"@types/request@^2.48.1": - version "2.48.8" - resolved "https://registry.yarnpkg.com/@types/request/-/request-2.48.8.tgz#0b90fde3b655ab50976cb8c5ac00faca22f5a82c" - integrity sha512-whjk1EDJPcAR2kYHRbFl/lKeeKYTi05A15K9bnLInCVroNDCtXce57xKdI0/rQaA3K+6q0eFyUBPmqfSndUZdQ== - dependencies: - "@types/caseless" "*" - "@types/node" "*" - "@types/tough-cookie" "*" - form-data "^2.5.0" - -"@types/resolve@^0.0.8": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.8.tgz#f26074d238e02659e323ce1a13d041eee280e194" - integrity sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ== - dependencies: - "@types/node" "*" - -"@types/responselike@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" - integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA== +"@types/responselike@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" + integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA== dependencies: "@types/node" "*" @@ -6941,11 +4882,6 @@ "@types/glob" "*" "@types/node" "*" -"@types/scheduler@*": - version "0.16.3" - resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.3.tgz#cef09e3ec9af1d63d2a6cc5b383a737e24e6dcf5" - integrity sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ== - "@types/secp256k1@^4.0.0", "@types/secp256k1@^4.0.1": version "4.0.3" resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.3.tgz#1b8e55d8e00f08ee7220b4d59a6abe89c37a901c" @@ -6968,14 +4904,6 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.4.tgz#0a41252ad431c473158b22f9bfb9a63df7541cff" integrity sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ== -"@types/send@*": - version "0.17.1" - resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.1.tgz#ed4932b8a2a805f1fe362a70f4e62d0ac994e301" - integrity sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q== - dependencies: - "@types/mime" "^1" - "@types/node" "*" - "@types/serve-static@*": version "1.15.1" resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.1.tgz#86b1753f0be4f9a1bee68d459fcda5be4ea52b5d" @@ -6989,11 +4917,6 @@ resolved "https://registry.yarnpkg.com/@types/shimmer/-/shimmer-1.0.4.tgz#8fa2317517280ecdd64078afc010809cb67c37b7" integrity sha512-hsughtxFsdJ9+Gxd/qH8zHE+KT6YEAxx9hJLoSXhxTBKHMQ2NMhN23fRJ75M9RRn2hDMNn13H3gS1EktA9VgDA== -"@types/solidity-parser-antlr@^0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@types/solidity-parser-antlr/-/solidity-parser-antlr-0.2.3.tgz#bb2d9c6511bf483afe4fc3e2714da8a924e59e3f" - integrity sha512-FoSyZT+1TTaofbEtGW1oC9wHND1YshvVeHerME/Jh6gIdHbBAWFW8A97YYqO/dpHcFjIwEPEepX0Efl2ckJgwA== - "@types/stack-utils@^2.0.0": version "2.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" @@ -7006,40 +4929,6 @@ dependencies: "@types/node" "*" -"@types/string-hash@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@types/string-hash/-/string-hash-1.1.1.tgz#4c336e61d1e13ce2d3efaaa5910005fd080e106b" - integrity sha512-ijt3zdHi2DmZxQpQTmozXszzDo78V4R3EdvX0jFMfnMH2ZzQSmCbaWOMPGXFUYSzSIdStv78HDjg32m5dxc+tA== - -"@types/tar-fs@*": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@types/tar-fs/-/tar-fs-2.0.1.tgz#6391dcad1b03dea2d79fac07371585ab54472bb1" - integrity sha512-qlsQyIY9sN7p221xHuXKNoMfUenOcvEBN4zI8dGsYbYCqHtTarXOEXSIgUnK+GcR0fZDse6pAIc5pIrCh9NefQ== - dependencies: - "@types/node" "*" - "@types/tar-stream" "*" - -"@types/tar-stream@*": - version "2.2.2" - resolved "https://registry.yarnpkg.com/@types/tar-stream/-/tar-stream-2.2.2.tgz#be9d0be9404166e4b114151f93e8442e6ab6fb1d" - integrity sha512-1AX+Yt3icFuU6kxwmPakaiGrJUwG44MpuiqPg4dSolRFk6jmvs4b3IbUol9wKDLIgU76gevn3EwE8y/DkSJCZQ== - dependencies: - "@types/node" "*" - -"@types/targz@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/targz/-/targz-1.0.0.tgz#cca3b2c87548d98f961b57306dc36d06f9fd15b2" - integrity sha512-kNFPOpsmdtT+DMXHuu5H7gXD5LlMHtS/kSQjuVY3QqxHQqGFV854o+EimC1GZ5/+iYZWzk9dNRiAUFbI/mvUsQ== - dependencies: - "@types/tar-fs" "*" - -"@types/targz@^1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@types/targz/-/targz-1.0.1.tgz#8b68a867b5dc28a755fd57e62d8b17f94e28462f" - integrity sha512-Uf5QxuLICkVOmSyDhPicBpIXk2oLIqaldObfr/WsTKTAPk666OpbeL0wZuNXwc5yg9OH1cBVj1rpMHGBJe4ilg== - dependencies: - "@types/tar-fs" "*" - "@types/tedious@^4.0.10": version "4.0.13" resolved "https://registry.yarnpkg.com/@types/tedious/-/tedious-4.0.13.tgz#31fa5968083218c114b9259b1653ef84a5ddbaa9" @@ -7054,28 +4943,11 @@ dependencies: "@types/node" "*" -"@types/tmp@^0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.1.0.tgz#19cf73a7bcf641965485119726397a096f0049bd" - integrity sha512-6IwZ9HzWbCq6XoQWhxLpDjuADodH/MKXRUIDFudvgjcVdjFknvmR+DNsoUeer4XPrEnrZs04Jj+kfV9pFsrhmA== - -"@types/tough-cookie@*": - version "4.0.2" - resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.2.tgz#6286b4c7228d58ab7866d19716f3696e03a09397" - integrity sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw== - "@types/utf8@^2.1.6": version "2.1.6" resolved "https://registry.yarnpkg.com/@types/utf8/-/utf8-2.1.6.tgz#430cabb71a42d0a3613cce5621324fe4f5a25753" integrity sha512-pRs2gYF5yoKYrgSaira0DJqVg2tFuF+Qjp838xS7K+mJyY2jJzjsrl6y17GbIa4uMRogMbxs+ghNCvKg6XyNrA== -"@types/web3-provider-engine@^14.0.0": - version "14.0.1" - resolved "https://registry.yarnpkg.com/@types/web3-provider-engine/-/web3-provider-engine-14.0.1.tgz#9ceb76af025e9359a28cff1f0fc4c19070c40ab7" - integrity sha512-SaAfLJY/40wKFDsNFwaNfwqFSL6kVhTx9JD18qM+Gaw1qdAXLYF/6E7TIqWEdoG4so6fki/zxURP5NsoCePYJw== - dependencies: - "@types/ethereum-protocol" "*" - "@types/web3@^1.0.18": version "1.2.2" resolved "https://registry.yarnpkg.com/@types/web3/-/web3-1.2.2.tgz#d95a101547ce625c5ebd0470baa5dbd4b9f3c015" @@ -7095,18 +4967,6 @@ resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== -"@types/yargs@^11.0.0": - version "11.1.8" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-11.1.8.tgz#b730ecb2bde209d12194cdf8bf9f12c4bd21965a" - integrity sha512-49Pmk3GBUOrs/ZKJodGMJeEeiulv2VdfAYpGgkTCSXpNWx7KCX36+PbrkItwzrjTDHO2QoEZDpbhFoMN1lxe9A== - -"@types/yargs@^13.0.2": - version "13.0.12" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.12.tgz#d895a88c703b78af0465a9de88aa92c61430b092" - integrity sha512-qCxJE1qgz2y0hA4pIxjBR+PelCH0U5CK1XJXFwCNqfmliatKp47UCXXE9Dyk1OXBDLvsCF57TqQEJaeLfDYEOQ== - dependencies: - "@types/yargs-parser" "*" - "@types/yargs@^17.0.8": version "17.0.24" resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.24.tgz#b3ef8d50ad4aa6aecf6ddc97c580a00f5aa11902" @@ -7119,34 +4979,6 @@ resolved "https://registry.yarnpkg.com/@wagmi/chains/-/chains-1.6.0.tgz#eb992ad28dbaaab729b5bcab3e5b461e8a035656" integrity sha512-5FRlVxse5P4ZaHG3GTvxwVANSmYJas1eQrTBHhjxVtqXoorm0aLmCHbhmN8Xo1yu09PaWKlleEvfE98yH4AgIw== -"@wagmi/cli@^1.0.1": - version "1.5.2" - resolved "https://registry.yarnpkg.com/@wagmi/cli/-/cli-1.5.2.tgz#11e767b8c5d1cfb5045b6ec63df6fa5001189bc4" - integrity sha512-UfLMYhW6mQBCjR8A5s01Chf9GpHzdpcuuBuzJ36QGXcMSJAxylz5ImVZWfCRV0ct1UruydjKVSW1QSI6azNxRQ== - dependencies: - abitype "0.8.7" - abort-controller "^3.0.0" - bundle-require "^3.1.2" - cac "^6.7.12" - change-case "^4.1.2" - chokidar "^3.5.3" - dedent "^0.7.0" - detect-package-manager "^2.0.1" - dotenv "^16.0.3" - dotenv-expand "^10.0.0" - esbuild "0.16.17" - execa "^6.1.0" - find-up "^6.3.0" - fs-extra "^10.1.0" - globby "^13.1.3" - node-fetch "^3.3.0" - ora "^6.1.2" - pathe "^1.0.0" - picocolors "^1.0.0" - prettier "^2.8.1" - viem "^1.0.0" - zod "^3.21.4" - "@yarnpkg/lockfile@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" @@ -7180,78 +5012,24 @@ abbrev@1, abbrev@^1.0.0: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -abbrev@1.0.x: - version "1.0.9" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" - integrity sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q== - -abi-to-sol@^0.6.6: - version "0.6.6" - resolved "https://registry.yarnpkg.com/abi-to-sol/-/abi-to-sol-0.6.6.tgz#2f0b7ea949f7015c1a7939d200b9e8d07f2c3c6d" - integrity sha512-PRn81rSpv6NXFPYQSw7ujruqIP6UkwZ/XoFldtiqCX8+2kHVc73xVaUVvdbro06vvBVZiwnxhEIGdI4BRMwGHw== - dependencies: - "@truffle/abi-utils" "^0.3.0" - "@truffle/contract-schema" "^3.3.1" - ajv "^6.12.5" - better-ajv-errors "^0.8.2" - neodoc "^2.0.2" - semver "^7.3.5" - source-map-support "^0.5.19" - optionalDependencies: - prettier "^2.7.1" - prettier-plugin-solidity "^1.0.0-dev.23" - -abi-to-sol@^0.7.0: - version "0.7.1" - resolved "https://registry.yarnpkg.com/abi-to-sol/-/abi-to-sol-0.7.1.tgz#76d55c35ab2932fda26c224e4194987517324a19" - integrity sha512-GcpyiHA+sTbmSEAbBWsXS5iO3WBGuqhsiBo3WH9VHthNFF/k438mXFJtS/SUxtm8HmbCMv/BnxokUX6w4y2eFg== - dependencies: - "@truffle/abi-utils" "^1.0.0" - "@truffle/contract-schema" "^3.3.1" - ajv "^6.12.5" - better-ajv-errors "^0.8.2" - neodoc "^2.0.2" - semver "^7.3.5" - source-map-support "^0.5.19" - optionalDependencies: - prettier "^2.7.1" - prettier-plugin-solidity "^1.0.0-dev.23" - -abitype@0.8.7: - version "0.8.7" - resolved "https://registry.yarnpkg.com/abitype/-/abitype-0.8.7.tgz#e4b3f051febd08111f486c0cc6a98fa72d033622" - integrity sha512-wQ7hV8Yg/yKmGyFpqrNZufCxbszDe5es4AZGYPBitocfSqXtjrTG9JMWFcc4N30ukl2ve48aBTwt7NJxVQdU3w== - abitype@0.9.3: version "0.9.3" resolved "https://registry.yarnpkg.com/abitype/-/abitype-0.9.3.tgz#294d25288ee683d72baf4e1fed757034e3c8c277" integrity sha512-dz4qCQLurx97FQhnb/EIYTk/ldQ+oafEDUqC0VVIeQS1Q48/YWt/9YNfMmp9SLFqN41ktxny3c8aYxHjmFIB/w== -abitype@0.9.8: - version "0.9.8" - resolved "https://registry.yarnpkg.com/abitype/-/abitype-0.9.8.tgz#1f120b6b717459deafd213dfbf3a3dd1bf10ae8c" - integrity sha512-puLifILdm+8sjyss4S+fsUN09obiT1g2YW6CtcQF+QDzxR0euzgEB29MZujC6zMk2a6SVmtttq1fc6+YFA7WYQ== - -abort-controller@3.0.0, abort-controller@^3.0.0: +abort-controller@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== dependencies: event-target-shim "^5.0.0" -abort-controller@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-2.0.3.tgz#b174827a732efadff81227ed4b8d1cc569baf20a" - integrity sha512-EPSq5wr2aFyAZ1PejJB32IX9Qd4Nwus+adnp7STYFM5/23nLPBazqZ1oor6ZqbH+4otaaGXTlC8RN5hq3C8w9Q== - dependencies: - event-target-shim "^5.0.0" - -abortcontroller-polyfill@^1.1.9, abortcontroller-polyfill@^1.7.3: +abortcontroller-polyfill@^1.7.3: version "1.7.5" resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz#6738495f4e901fbb57b6c0611d0c75f76c485bed" integrity sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ== -abstract-level@1.0.3, abstract-level@^1.0.0, abstract-level@^1.0.2, abstract-level@^1.0.3: +abstract-level@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/abstract-level/-/abstract-level-1.0.3.tgz#78a67d3d84da55ee15201486ab44c09560070741" integrity sha512-t6jv+xHy+VYwc4xqZMn2Pa9DjcdzvzZmQGRjTFc8spIbRGHgBrEKbPq+rYXc7CCo0lxgYvSgKVg9qZAhpVQSjA== @@ -7276,50 +5054,7 @@ abstract-leveldown@7.2.0, abstract-leveldown@^7.2.0: level-supports "^2.0.1" queue-microtask "^1.2.3" -abstract-leveldown@^5.0.0, abstract-leveldown@~5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz#f7128e1f86ccabf7d2893077ce5d06d798e386c6" - integrity sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A== - dependencies: - xtend "~4.0.0" - -abstract-leveldown@^6.2.1: - version "6.3.0" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-6.3.0.tgz#d25221d1e6612f820c35963ba4bd739928f6026a" - integrity sha512-TU5nlYgta8YrBMNpc9FwQzRbiXsj49gsALsXadbGHt9CROPzX5fB0rWDR5mtdpOOKa5XqRFpbj1QroPAoPzVjQ== - dependencies: - buffer "^5.5.0" - immediate "^3.2.3" - level-concat-iterator "~2.0.0" - level-supports "~1.0.0" - xtend "~4.0.0" - -abstract-leveldown@~2.6.0: - version "2.6.3" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz#1c5e8c6a5ef965ae8c35dfb3a8770c476b82c4b8" - integrity sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA== - dependencies: - xtend "~4.0.0" - -abstract-leveldown@~2.7.1: - version "2.7.2" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz#87a44d7ebebc341d59665204834c8b7e0932cc93" - integrity sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w== - dependencies: - xtend "~4.0.0" - -abstract-leveldown@~6.2.1, abstract-leveldown@~6.2.3: - version "6.2.3" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz#036543d87e3710f2528e47040bc3261b77a9a8eb" - integrity sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ== - dependencies: - buffer "^5.5.0" - immediate "^3.2.3" - level-concat-iterator "~2.0.0" - level-supports "~1.0.0" - xtend "~4.0.0" - -accepts@^1.3.5, accepts@~1.3.8: +accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== @@ -7332,21 +5067,11 @@ acorn-import-assertions@^1.9.0: resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== -acorn-jsx@^5.0.0: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - acorn-walk@^8.1.1: version "8.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== -acorn@^6.0.7: - version "6.4.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" - integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== - acorn@^8.4.1: version "8.8.2" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" @@ -7367,7 +5092,7 @@ aes-js@3.0.0: resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== -aes-js@^3.1.1, aes-js@^3.1.2: +aes-js@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== @@ -7379,13 +5104,6 @@ agent-base@6, agent-base@^6.0.2: dependencies: debug "4" -agent-base@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" - integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg== - dependencies: - es6-promisify "^5.0.0" - agentkeepalive@^4.2.1: version "4.3.0" resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.3.0.tgz#bb999ff07412653c1803b3ced35e50729830a255" @@ -7403,14 +5121,7 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv-formats@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" - integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== - dependencies: - ajv "^8.0.0" - -ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.5, ajv@^6.6.1, ajv@^6.9.1: +ajv@^6.10.0, ajv@^6.12.3: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -7420,49 +5131,17 @@ ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.5, ajv@^6.6.1, ajv@^6.9.1: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.0.0, ajv@^8.6.3: - version "8.12.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" - integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== - dependencies: - fast-deep-equal "^3.1.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - uri-js "^4.2.2" - -algebrite@^0.2.23: - version "0.2.23" - resolved "https://registry.yarnpkg.com/algebrite/-/algebrite-0.2.23.tgz#e0490d7c6ea7ddb0dc46fc98d1026415dfe2d853" - integrity sha512-9eLHJVW3QqIZMq679gqbqEl/DXux4KvSWFyvLJ75ovl92RG3lm5mkL5UmjKcUveUH5WF1/TImP8UqiWbRZJTKg== - dependencies: - big-integer "^1.6.15" - -amdefine@>=0.0.4: - version "1.0.1" - resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" - integrity sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg== - ansi-color@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/ansi-color/-/ansi-color-0.2.1.tgz#3e75c037475217544ed763a8db5709fa9ae5bf9a" integrity sha512-bF6xLaZBLpOQzgYUtYEhJx090nPSZk1BQ/q2oyBK9aMMcJHzx9uXGCjI2Y+LebsN4Jwoykr0V9whbPiogdyHoQ== -ansi-colors@3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" - integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== - -ansi-colors@4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" - integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== - ansi-colors@^4.1.1, ansi-colors@^4.1.3: version "4.1.3" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== -ansi-escapes@^3.1.0, ansi-escapes@^3.2.0: +ansi-escapes@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== @@ -7494,11 +5173,6 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-regex@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" - integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== - ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -7518,44 +5192,12 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== -ansi-styles@^6.1.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" - integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== - -ansi-wrap@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" - integrity sha512-ZyznvL8k/FZeQHr2T6LzcJ/+vBApDnMNZvfVFy3At0knswWd6rJ3/0Hhmpu8oqa6C92npmozs890sX9Dl6q+Qw== - -ansi-yellow@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-yellow/-/ansi-yellow-0.1.1.tgz#cb9356f2f46c732f0e3199e6102955a77da83c1d" - integrity sha512-6E3D4BQLXHLl3c/NwirWVZ+BCkMq2qsYxdeAGGOijKrx09FaqU+HktFL6QwAwNvgJiMLnv6AQ2C1gFZx0h1CBg== - dependencies: - ansi-wrap "0.1.0" - ansicolors@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979" integrity sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg== -antlr4@4.7.1: - version "4.7.1" - resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.7.1.tgz#69984014f096e9e775f53dd9744bf994d8959773" - integrity sha512-haHyTW7Y9joE5MVs37P2lNYfU2RWBLfcRDD8OWldcdZm5TiCE91B5Xl1oWSwiDUSd4rlExpt2pu1fksYQjRBYQ== - -antlr4ts@^0.5.0-alpha.4: - version "0.5.0-alpha.4" - resolved "https://registry.yarnpkg.com/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz#71702865a87478ed0b40c0709f422cf14d51652a" - integrity sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ== - -any-promise@1.3.0, any-promise@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" - integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== - -anymatch@^3.0.3, anymatch@~3.1.1, anymatch@~3.1.2: +anymatch@^3.0.3: version "3.1.3" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== @@ -7563,116 +5205,6 @@ anymatch@^3.0.3, anymatch@~3.1.1, anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" -apollo-datasource@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/apollo-datasource/-/apollo-datasource-3.3.2.tgz#5711f8b38d4b7b53fb788cb4dbd4a6a526ea74c8" - integrity sha512-L5TiS8E2Hn/Yz7SSnWIVbZw0ZfEIXZCa5VUiVxD9P53JvSrf4aStvsFDlGWPvpIdCR+aly2CfoB79B9/JjKFqg== - dependencies: - "@apollo/utils.keyvaluecache" "^1.0.1" - apollo-server-env "^4.2.1" - -apollo-reporting-protobuf@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/apollo-reporting-protobuf/-/apollo-reporting-protobuf-3.4.0.tgz#6edd31f09d4a3704d9e808d1db30eca2229ded26" - integrity sha512-h0u3EbC/9RpihWOmcSsvTW2O6RXVaD/mPEjfrPkxRPTEPWqncsgOoRJw+wih4OqfH3PvTJvoEIf4LwKrUaqWog== - dependencies: - "@apollo/protobufjs" "1.2.6" - -apollo-server-core@^3.12.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-3.12.0.tgz#8aa2a7329ce6fe1823290c45168c749db01548df" - integrity sha512-hq7iH6Cgldgmnjs9FVSZeKWRpi0/ZR+iJ1arzeD2VXGxxgk1mAm/cz1Tx0TYgegZI+FvvrRl0UhKEx7sLnIxIg== - dependencies: - "@apollo/utils.keyvaluecache" "^1.0.1" - "@apollo/utils.logger" "^1.0.0" - "@apollo/utils.usagereporting" "^1.0.0" - "@apollographql/apollo-tools" "^0.5.3" - "@apollographql/graphql-playground-html" "1.6.29" - "@graphql-tools/mock" "^8.1.2" - "@graphql-tools/schema" "^8.0.0" - "@josephg/resolvable" "^1.0.0" - apollo-datasource "^3.3.2" - apollo-reporting-protobuf "^3.4.0" - apollo-server-env "^4.2.1" - apollo-server-errors "^3.3.1" - apollo-server-plugin-base "^3.7.2" - apollo-server-types "^3.8.0" - async-retry "^1.2.1" - fast-json-stable-stringify "^2.1.0" - graphql-tag "^2.11.0" - loglevel "^1.6.8" - lru-cache "^6.0.0" - node-abort-controller "^3.0.1" - sha.js "^2.4.11" - uuid "^9.0.0" - whatwg-mimetype "^3.0.0" - -apollo-server-env@^4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/apollo-server-env/-/apollo-server-env-4.2.1.tgz#ea5b1944accdbdba311f179e4dfaeca482c20185" - integrity sha512-vm/7c7ld+zFMxibzqZ7SSa5tBENc4B0uye9LTfjJwGoQFY5xsUPH5FpO5j0bMUDZ8YYNbrF9SNtzc5Cngcr90g== - dependencies: - node-fetch "^2.6.7" - -apollo-server-errors@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/apollo-server-errors/-/apollo-server-errors-3.3.1.tgz#ba5c00cdaa33d4cbd09779f8cb6f47475d1cd655" - integrity sha512-xnZJ5QWs6FixHICXHxUfm+ZWqqxrNuPlQ+kj5m6RtEgIpekOPssH/SD9gf2B4HuWV0QozorrygwZnux8POvyPA== - -apollo-server-express@^3.12.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-3.12.0.tgz#a6e392bb0427544b8c7e5d841ef07f7691b0c105" - integrity sha512-m8FaGPUfDOEGSm7QRWRmUUGjG/vqvpQoorkId9/FXkC57fz/A59kEdrzkMt9538Xgsa5AV+X4MEWLJhTvlW3LQ== - dependencies: - "@types/accepts" "^1.3.5" - "@types/body-parser" "1.19.2" - "@types/cors" "2.8.12" - "@types/express" "4.17.14" - "@types/express-serve-static-core" "4.17.31" - accepts "^1.3.5" - apollo-server-core "^3.12.0" - apollo-server-types "^3.8.0" - body-parser "^1.19.0" - cors "^2.8.5" - parseurl "^1.3.3" - -apollo-server-plugin-base@^3.7.2: - version "3.7.2" - resolved "https://registry.yarnpkg.com/apollo-server-plugin-base/-/apollo-server-plugin-base-3.7.2.tgz#c19cd137bc4c993ba2490ba2b571b0f3ce60a0cd" - integrity sha512-wE8dwGDvBOGehSsPTRZ8P/33Jan6/PmL0y0aN/1Z5a5GcbFhDaaJCjK5cav6npbbGL2DPKK0r6MPXi3k3N45aw== - dependencies: - apollo-server-types "^3.8.0" - -apollo-server-types@^3.8.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/apollo-server-types/-/apollo-server-types-3.8.0.tgz#d976b6967878681f715fe2b9e4dad9ba86b1346f" - integrity sha512-ZI/8rTE4ww8BHktsVpb91Sdq7Cb71rdSkXELSwdSR0eXu600/sY+1UXhTWdiJvk+Eq5ljqoHLwLbY2+Clq2b9A== - dependencies: - "@apollo/utils.keyvaluecache" "^1.0.1" - "@apollo/utils.logger" "^1.0.0" - apollo-reporting-protobuf "^3.4.0" - apollo-server-env "^4.2.1" - -apollo-server@^3.11.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/apollo-server/-/apollo-server-3.12.0.tgz#bd43d6dadb8cb16ed34edfc6ad97a81b1fab748a" - integrity sha512-wZHLgBoIdGxr/YpPTG5RwNnS+B2y70T/nCegCnU6Yl+H3PXB92OIguLMhdJIZVjukIOhiQT12dNIehqLQ+1hMQ== - dependencies: - "@types/express" "4.17.14" - apollo-server-core "^3.12.0" - apollo-server-express "^3.12.0" - express "^4.17.1" - -app-module-path@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/app-module-path/-/app-module-path-2.2.0.tgz#641aa55dfb7d6a6f0a8141c4b9c0aa50b6c24dd5" - integrity sha512-gkco+qxENJV+8vFcDiiFhuoSvRXb2a/QPqpSoWhVz829VNJfOTnELbBmPmNKFxf3xdNnw4DWCkzkDaavcX/1YQ== - -aproba@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== - "aproba@^1.0.3 || ^2.0.0", aproba@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" @@ -7686,14 +5218,6 @@ are-we-there-yet@^3.0.0: delegates "^1.0.0" readable-stream "^3.6.0" -are-we-there-yet@~1.1.2: - version "1.1.7" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz#b15474a932adab4ff8a50d9adfa7e4e926f21146" - integrity sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - arg@^4.1.0: version "4.1.3" resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" @@ -7711,48 +5235,17 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -argsarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/argsarray/-/argsarray-0.0.1.tgz#6e7207b4ecdb39b0af88303fa5ae22bda8df61cb" - integrity sha512-u96dg2GcAKtpTrBdDoFIM7PjcBA+6rSP0OR94MOReNRyUECL6MtQt5XXmRr4qrftYaef9+l5hcpO5te7sML1Cg== - argv@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/argv/-/argv-0.0.2.tgz#ecbd16f8949b157183711b1bda334f37840185ab" integrity sha512-dEamhpPEwRUBpLNHeuCm/v+g0anFByHahxodVO/BbAarHVBBg2MccCwf9K+o1Pof+2btdnkJelYVUWjW/VrATw== -armlet@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/armlet/-/armlet-2.7.0.tgz#21c4f9884de17fd75785d8468a669c0f12b01370" - integrity sha512-+j89VqGIf/E9a6aBaJa1OG9AZ93OnlfBzZz76TegU40ELcHcKb5b05XU7a1xKJsikdt6Da/fRaYHQ36oyLLj9Q== - dependencies: - http-errors "^1.7.1" - humanize-duration "^3.17.0" - isomorphic-fetch "^2.2.1" - omni-fetch "^0.2.3" - request "^2.88.0" - -arr-diff@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-1.1.0.tgz#687c32758163588fef7de7b36fabe495eb1a399a" - integrity sha512-OQwDZUqYaQwyyhDJHThmzId8daf4/RFNLaeh3AevmSeZ5Y7ug4Ga/yKc6l6kTZOBW781rCj103ZuTh8GAsB3+Q== - dependencies: - arr-flatten "^1.0.1" - array-slice "^0.2.3" - -arr-diff@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" - integrity sha512-dtXTVMkh6VkEEA7OhXnN1Ecb8aAGFdZ1LFxtOCoqj4qkyOJMt7+qs6Ahdy6p/NQCPYsRSXXivhSB/J5E9jmYKA== - dependencies: - arr-flatten "^1.0.1" - arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" integrity sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA== -arr-flatten@^1.0.1, arr-flatten@^1.1.0: +arr-flatten@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== @@ -7762,20 +5255,6 @@ arr-union@^3.1.0: resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q== -array-back@^1.0.3, array-back@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-1.0.4.tgz#644ba7f095f7ffcf7c43b5f0dc39d3c1f03c063b" - integrity sha512-1WxbZvrmyhkNoeYcizokbmh5oiOCIfyvGtcqbK3Ls1v1fKcquzxnQSceOx6tzq7jmai2kFLWIpGND2cLhH6TPw== - dependencies: - typical "^2.6.0" - -array-back@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-2.0.0.tgz#6877471d51ecc9c9bfa6136fb6c7d5fe69748022" - integrity sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw== - dependencies: - typical "^2.6.1" - array-buffer-byte-length@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" @@ -7799,11 +5278,6 @@ array-ify@^1.0.0: resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" integrity sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng== -array-slice@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5" - integrity sha512-rlVfZW/1Ph2SNySXwR9QYkChp8EkOEiTMO5Vwx60usw04i4nWemkm9RXmQqgkQFaLHsqLuADvjp6IfgL9l2M8Q== - array-union@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" @@ -7821,11 +5295,6 @@ array-uniq@^1.0.1: resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" integrity sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q== -array-unique@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" - integrity sha512-G2n5bG5fSUCpnsXz4+8FUkYsGPkNfLn9YvS66U5qbTIXI2Ynnlo4Bi42bWv+omKUCqz+ejzfClwne0alJWJPhg== - array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" @@ -7841,28 +5310,6 @@ array.prototype.flat@^1.2.3: es-abstract "^1.22.1" es-shim-unscopables "^1.0.0" -array.prototype.map@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/array.prototype.map/-/array.prototype.map-1.0.5.tgz#6e43c2fee6c0fb5e4806da2dc92eb00970809e55" - integrity sha512-gfaKntvwqYIuC7mLLyv2wzZIJqrRhn5PZ9EfFejSx6a78sV7iDsGpG9P+3oUPtm1Rerqm6nrKS4FYuTIvWfo3g== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - es-array-method-boxes-properly "^1.0.0" - is-string "^1.0.7" - -array.prototype.reduce@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz#6b20b0daa9d9734dd6bc7ea66b5bbce395471eac" - integrity sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - es-array-method-boxes-properly "^1.0.0" - is-string "^1.0.7" - arraybuffer.prototype.slice@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz#98bd561953e3e74bb34938e77647179dfe6e9f12" @@ -7876,7 +5323,7 @@ arraybuffer.prototype.slice@^1.0.2: is-array-buffer "^3.0.2" is-shared-array-buffer "^1.0.2" -arrify@^1.0.0, arrify@^1.0.1: +arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== @@ -7886,29 +5333,11 @@ arrify@^2.0.0, arrify@^2.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== -asap@^2.0.0, asap@~2.0.6: +asap@^2.0.0: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== -ascli@~1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ascli/-/ascli-1.0.1.tgz#bcfa5974a62f18e81cabaeb49732ab4a88f906bc" - integrity sha512-JGQaNxpaCJz9Bd1JvVaFIHuWn9S+l3xhN17R0V/vmUDiGE0QngNMXhjlqpwqV+91plWz9Fg+Lt28Lj7p5vjs8A== - dependencies: - colour "~0.7.1" - optjs "~3.2.2" - -asn1.js@^5.2.0: - version "5.4.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" - integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== - dependencies: - bn.js "^4.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - safer-buffer "^2.1.0" - asn1@~0.2.3: version "0.2.6" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" @@ -7928,27 +5357,12 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== -assertion-error@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" - integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== - assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw== -astral-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== - -async-each@^1.0.1: - version "1.0.6" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.6.tgz#52f1d9403818c179b7561e11a5d1b77eb2160e77" - integrity sha512-c646jH1avxr+aVpndVMeAfYw7wAa6idufrlN3LPA4PmKS0QEGp6PIC9nwz0WQkkvBGAMEki3pFdtxaF39J9vvg== - -async-eventemitter@0.2.4, async-eventemitter@^0.2.2: +async-eventemitter@0.2.4: version "0.2.4" resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.4.tgz#f5e7c8ca7d3e46aab9ec40a292baf686a0bafaca" integrity sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw== @@ -7960,26 +5374,7 @@ async-limiter@~1.0.0: resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== -async-mutex@^0.2.6: - version "0.2.6" - resolved "https://registry.yarnpkg.com/async-mutex/-/async-mutex-0.2.6.tgz#0d7a3deb978bc2b984d5908a2038e1ae2e54ff40" - integrity sha512-Hs4R+4SPgamu6rSGW8C7cV9gaWUKEHykfzCCvIRuaVv636Ju10ZdeUbvb4TBEW0INuq2DHZqXbK4Nd3yG4RaRw== - dependencies: - tslib "^2.0.0" - -async-retry@^1.2.1: - version "1.3.3" - resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.3.3.tgz#0e7f36c04d8478e7a58bdbed80cedf977785f280" - integrity sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw== - dependencies: - retry "0.13.1" - -async@1.x, async@^1.3.0, async@^1.4.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - integrity sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w== - -async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.5.0, async@^2.6.1: +async@^2.4.0: version "2.6.3" resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== @@ -7993,7 +5388,7 @@ async@^2.6.4: dependencies: lodash "^4.17.14" -async@^3.2.3, async@^3.2.4: +async@^3.2.3: version "3.2.4" resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== @@ -8018,11 +5413,6 @@ atob@^2.1.2: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== -atomically@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/atomically/-/atomically-1.7.0.tgz#c07a0458432ea6dbc9a3506fffa424b48bccaafe" - integrity sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w== - available-typed-arrays@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" @@ -8054,48 +5444,6 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3" integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg== -axios-retry@^3.1.9: - version "3.4.0" - resolved "https://registry.yarnpkg.com/axios-retry/-/axios-retry-3.4.0.tgz#f464dbe9408e5aa78fa319afd38bb69b533d8854" - integrity sha512-VdgaP+gHH4iQYCCNUWF2pcqeciVOdGrBBAYUfTY+wPcO5Ltvp/37MLFNCmJKo7Gj3SHvCSdL8ouI1qLYJN3liA== - dependencies: - "@babel/runtime" "^7.15.4" - is-retry-allowed "^2.2.0" - -axios-retry@^3.7.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/axios-retry/-/axios-retry-3.8.0.tgz#a174af633ef143a9f5642b9e4afe65c2017936b5" - integrity sha512-CfIsQyWNc5/AE7x/UEReRUadiBmQeoBpSEC+4QyGLJMswTsP1tz0GW2YYPnE7w9+ESMef5zOgLDFpHynNyEZ1w== - dependencies: - "@babel/runtime" "^7.15.4" - is-retry-allowed "^2.2.0" - -axios@1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.2.4.tgz#6555dd955d2efa9b8f4cb4cb0b3371b7b243537a" - integrity sha512-lIQuCfBJvZB/Bv7+RWUqEJqNShGOVpk9v7P0ZWx5Ip0qY6u7JBAU6dzQPMLasU9vHL2uD8av/1FDJXj7n6c39w== - dependencies: - follow-redirects "^1.15.0" - form-data "^4.0.0" - proxy-from-env "^1.1.0" - -axios@1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.5.0.tgz#f02e4af823e2e46a9768cfc74691fdd0517ea267" - integrity sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ== - dependencies: - follow-redirects "^1.15.0" - form-data "^4.0.0" - proxy-from-env "^1.1.0" - -axios@^0.18.0: - version "0.18.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.18.1.tgz#ff3f0de2e7b5d180e757ad98000f1081b87bcea3" - integrity sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g== - dependencies: - follow-redirects "1.5.10" - is-buffer "^2.0.2" - axios@^0.21.1: version "0.21.4" resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" @@ -8103,20 +5451,6 @@ axios@^0.21.1: dependencies: follow-redirects "^1.14.0" -axios@^0.25.0: - version "0.25.0" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.25.0.tgz#349cfbb31331a9b4453190791760a8d35b093e0a" - integrity sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g== - dependencies: - follow-redirects "^1.14.7" - -axios@^0.26.1: - version "0.26.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.26.1.tgz#1ede41c51fcf51bbbd6fd43669caaa4f0495aaa9" - integrity sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA== - dependencies: - follow-redirects "^1.14.8" - axios@^1.0.0: version "1.3.6" resolved "https://registry.yarnpkg.com/axios/-/axios-1.3.6.tgz#1ace9a9fb994314b5f6327960918406fa92c6646" @@ -8160,30 +5494,6 @@ babel-plugin-jest-hoist@^29.5.0: "@types/babel__core" "^7.1.14" "@types/babel__traverse" "^7.0.6" -babel-plugin-polyfill-corejs2@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz#5d1bd3836d0a19e1b84bbf2d9640ccb6f951c122" - integrity sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q== - dependencies: - "@babel/compat-data" "^7.17.7" - "@babel/helper-define-polyfill-provider" "^0.3.3" - semver "^6.1.1" - -babel-plugin-polyfill-corejs3@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz#56ad88237137eade485a71b52f72dbed57c6230a" - integrity sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.3.3" - core-js-compat "^3.25.1" - -babel-plugin-polyfill-regenerator@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz#390f91c38d90473592ed43351e801a9d3e0fd747" - integrity sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.3.3" - babel-preset-current-node-syntax@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" @@ -8218,13 +5528,6 @@ babel-runtime@^6.26.0: core-js "^2.4.0" regenerator-runtime "^0.11.0" -backoff@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f" - integrity sha512-wC5ihrnUXmR2douXmXLCe5O3zg3GKIyvRi/hi58a/XyRxVI+3/yM0PYueQOZXPXQ9pxBislYkw+sF9b7C/RuMA== - dependencies: - precond "0.2" - balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -8272,19 +5575,6 @@ before-after-hook@^2.2.0: resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.3.tgz#c51e809c81a4e354084422b9b26bad88249c517c" integrity sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ== -better-ajv-errors@^0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/better-ajv-errors/-/better-ajv-errors-0.8.2.tgz#9abf27e19d2cee60f400753510f7a3a96d655adf" - integrity sha512-FnODTBJSQSHmJXDLPiC7ca0dC4S1HSTPv1+Hg2sm/C71i3Dj0l1jcUEaq/3OQ6MmnUveshTsUvUj65pDSr3Qow== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/runtime" "^7.0.0" - chalk "^2.4.1" - core-js "^3.2.1" - json-to-ast "^2.0.3" - jsonpointer "^5.0.0" - leven "^3.1.0" - better-path-resolve@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/better-path-resolve/-/better-path-resolve-1.0.0.tgz#13a35a1104cdd48a7b74bf8758f96a1ee613f99d" @@ -8297,7 +5587,7 @@ big-integer@1.6.36: resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.36.tgz#78631076265d4ae3555c04f85e7d9d2f3a071a36" integrity sha512-t70bfa7HYEA1D9idDbmuv7YbsbVkQ+Hp+8KFSul4aE5e/i1bjCNIRYJZlA8Q8p0r9T8cF/RVvwUgRA//FydEyg== -big-integer@^1.6.15, big-integer@^1.6.44: +big-integer@^1.6.44: version "1.6.51" resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686" integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg== @@ -8307,17 +5597,12 @@ big.js@^6.0.3: resolved "https://registry.yarnpkg.com/big.js/-/big.js-6.2.1.tgz#7205ce763efb17c2e41f26f121c420c6a7c2744f" integrity sha512-bCtHMwL9LeDIozFn+oNhhFoq+yQ3BNdnsLSASUxLciOb1vgvpHsIO1dsENiGMgbb4SkP5TrzWzRiLddn8ahVOQ== -bigi@^1.1.0, bigi@^1.4.2: +bigi@^1.4.2: version "1.4.2" resolved "https://registry.yarnpkg.com/bigi/-/bigi-1.4.2.tgz#9c665a95f88b8b08fc05cfd731f561859d725825" integrity sha512-ddkU+dFIuEIW8lE7ZwdIAf2UPoM90eaprg5m3YXAVVTmKlqV/9BX4A2M8BOK2yOq6/VgZFVhK6QAxJebhlbhzw== -bigint-crypto-utils@^3.0.23: - version "3.2.2" - resolved "https://registry.yarnpkg.com/bigint-crypto-utils/-/bigint-crypto-utils-3.2.2.tgz#e30a49ec38357c6981cd3da5aaa6480b1f752ee4" - integrity sha512-U1RbE3aX9ayCUVcIPHuPDPKcK3SFOXf93J1UK/iHlJuQB7bhagPIX06/CLpLEsDThJ7KA4Dhrnzynl+d2weTiw== - -bignumber.js@7.2.1, bignumber.js@9.0.0, bignumber.js@9.1.0, bignumber.js@^7.2.0, bignumber.js@^7.2.1, bignumber.js@^9.0.0, bignumber.js@^9.0.1, bignumber.js@^9.1.2, "bignumber.js@git+https://github.com/debris/bignumber.js#master", "bignumber.js@git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2", bignumber.js@~9.0.2: +bignumber.js@9.0.0, bignumber.js@^7.2.1, bignumber.js@^9.0.0, bignumber.js@^9.0.1, bignumber.js@^9.1.2: version "9.0.0" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.0.tgz#805880f84a329b5eac6e7cb6f8274b6d82bdf075" integrity sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A== @@ -8334,11 +5619,6 @@ bin-links@^3.0.0: rimraf "^3.0.0" write-file-atomic "^4.0.0" -binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== - bindings@^1.2.1, bindings@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" @@ -8358,7 +5638,7 @@ bip32@3.1.0, bip32@^3.1.0: typeforce "^1.11.5" wif "^2.0.6" -bip39@2.5.0, bip39@^2.2.0, bip39@^2.5.0, "bip39@https://github.com/bitcoinjs/bip39#d8ea080a18b40f301d4e2219a2991cd2417e83c2": +"bip39@https://github.com/bitcoinjs/bip39#d8ea080a18b40f301d4e2219a2991cd2417e83c2": version "3.0.3" resolved "https://github.com/bitcoinjs/bip39#d8ea080a18b40f301d4e2219a2991cd2417e83c2" dependencies: @@ -8367,13 +5647,6 @@ bip39@2.5.0, bip39@^2.2.0, bip39@^2.5.0, "bip39@https://github.com/bitcoinjs/bip pbkdf2 "^3.0.9" randombytes "^2.0.1" -bip66@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22" - integrity sha512-nemMHz95EmS38a26XbbdxIYj5csHd3RMP3H5bwQknX0WYHF01qhpufP42mLOwVICuH2JmhIhXiWs89MfUGL7Xw== - dependencies: - safe-buffer "^5.0.1" - bl@^1.0.0: version "1.2.3" resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.3.tgz#1e8dd80142eac80d7158c9dccc047fb620e035e7" @@ -8391,15 +5664,6 @@ bl@^4.0.3, bl@^4.1.0: inherits "^2.0.4" readable-stream "^3.4.0" -bl@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/bl/-/bl-5.1.0.tgz#183715f678c7188ecef9fe475d90209400624273" - integrity sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ== - dependencies: - buffer "^6.0.3" - inherits "^2.0.4" - readable-stream "^3.4.0" - blakejs@^1.1.0: version "1.2.1" resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" @@ -8410,11 +5674,6 @@ blakejs@^1.1.0: resolved "https://registry.yarnpkg.com/@celo/blind-threshold-bls/-/blind-threshold-bls-1.0.0-beta.tgz#6c46e55c3720d99929d6d34dd3770b1623a09900" integrity sha512-sk9XLvbv0M0TJKJPHPc8FkIRTfP/PiPHeyKXPBTMZBW8URL4pRix9IfcT98zT5sA7hvMDJwgw3p3tM/L6Z1iGw== -bluebird@^2.9.33: - version "2.11.0" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1" - integrity sha512-UfFSr22dmHPQqPP9XWHRhq+gWnHCYguQGkXQlbyPtW5qTnhFWA8/iXg765tH0cAjy7l/zPJ1aBTO0g5XgA7kvQ== - bluebird@^3.5.0, bluebird@^3.5.2: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" @@ -8425,22 +5684,17 @@ bn.js@4.11.6: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" integrity sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA== -bn.js@4.11.8: - version "4.11.8" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" - integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== - bn.js@4.11.9: version "4.11.9" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828" integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw== -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.0, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.11.9, bn.js@^4.4.0: +bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.11.9: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== -bn.js@^5.0.0, bn.js@^5.1.0, bn.js@^5.1.2, bn.js@^5.1.3, bn.js@^5.2.0, bn.js@^5.2.1: +bn.js@^5.1.0, bn.js@^5.1.2, bn.js@^5.1.3, bn.js@^5.2.0, bn.js@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== @@ -8463,7 +5717,7 @@ body-parser@1.20.1: type-is "~1.6.18" unpipe "1.0.0" -body-parser@^1.16.0, body-parser@^1.19.0: +body-parser@^1.16.0: version "1.20.2" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== @@ -8501,15 +5755,6 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" -braces@^1.8.0, braces@^1.8.2: - version "1.8.5" - resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" - integrity sha512-xU7bpz2ytJl1bH9cgIurjpg/n8Gohy9GTw81heDYLJQ4RU60dlyJsa+atVF2pI0yMMvKxI9HkKwjePCj5XI1hw== - dependencies: - expand-range "^1.8.1" - preserve "^0.2.0" - repeat-element "^1.1.2" - braces@^2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" @@ -8526,7 +5771,7 @@ braces@^2.3.1: split-string "^3.0.2" to-regex "^3.0.1" -braces@^3.0.2, braces@~3.0.2: +braces@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -8540,27 +5785,12 @@ breakword@^1.0.5: dependencies: wcwidth "^1.0.1" -brorand@^1.0.1, brorand@^1.1.0: +brorand@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== -browser-level@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browser-level/-/browser-level-1.0.1.tgz#36e8c3183d0fe1c405239792faaab5f315871011" - integrity sha512-XECYKJ+Dbzw0lbydyQuJzwNXtOpbMSq737qxJN11sIRTErOMShvDpbzTlgju7orJKvx4epULolZAuJGLzCmWRQ== - dependencies: - abstract-level "^1.0.2" - catering "^2.1.1" - module-error "^1.0.2" - run-parallel-limit "^1.1.0" - -browser-stdout@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== - -browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6, browserify-aes@^1.2.0: +browserify-aes@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== @@ -8572,49 +5802,7 @@ browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6, browserify- inherits "^2.0.1" safe-buffer "^5.0.1" -browserify-cipher@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== - dependencies: - browserify-aes "^1.0.4" - browserify-des "^1.0.0" - evp_bytestokey "^1.0.0" - -browserify-des@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" - integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== - dependencies: - cipher-base "^1.0.1" - des.js "^1.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -browserify-rsa@^4.0.0, browserify-rsa@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" - integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== - dependencies: - bn.js "^5.0.0" - randombytes "^2.0.1" - -browserify-sign@^4.0.0: - version "4.2.2" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.2.tgz#e78d4b69816d6e3dd1c747e64e9947f9ad79bc7e" - integrity sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg== - dependencies: - bn.js "^5.2.1" - browserify-rsa "^4.1.0" - create-hash "^1.2.0" - create-hmac "^1.1.7" - elliptic "^6.5.4" - inherits "^2.0.4" - parse-asn1 "^5.1.6" - readable-stream "^3.6.2" - safe-buffer "^5.2.1" - -browserslist@^4.21.3, browserslist@^4.21.5: +browserslist@^4.21.3: version "4.21.5" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7" integrity sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w== @@ -8631,11 +5819,6 @@ bs-logger@0.x: dependencies: fast-json-stable-stringify "2.x" -bs58@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/bs58/-/bs58-2.0.1.tgz#55908d58f1982aba2008fa1bed8f91998a29bf8d" - integrity sha512-77ld2g7Hn1GyIUpuUVfbZdhO1q9R9gv/GYam4HAeAW/tzhQDrbJ2ZttN1tIe4hmKrWFE+oUtAhBNx/EA5SVdTg== - bs58@^4.0.0, bs58@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" @@ -8659,11 +5842,6 @@ bser@2.1.1: dependencies: node-int64 "^0.4.0" -btoa@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/btoa/-/btoa-1.2.1.tgz#01a9909f8b2c93f6bf680ba26131eb30f7fa3d73" - integrity sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g== - buffer-alloc-unsafe@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" @@ -8677,11 +5855,6 @@ buffer-alloc@^1.2.0: buffer-alloc-unsafe "^1.1.0" buffer-fill "^1.0.0" -buffer-crc32@~0.2.3: - version "0.2.13" - resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ== - buffer-equal-constant-time@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" @@ -8692,7 +5865,7 @@ buffer-fill@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" integrity sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ== -buffer-from@1.1.2, buffer-from@^1.0.0, buffer-from@^1.1.1: +buffer-from@^1.0.0, buffer-from@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== @@ -8707,23 +5880,11 @@ buffer-to-arraybuffer@^0.0.5: resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz#6064a40fa76eb43c723aba9ef8f6e1216d10511a" integrity sha512-3dthu5CYiVB1DEJp61FtApNnNndTckcqe4pFcLdvHtrpG+kcyekCJKg4MRiDcFW7A6AODnXB9U4dwQiCW5kzJQ== -buffer-writer@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04" - integrity sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw== - buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== -buffer-xor@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-2.0.2.tgz#34f7c64f04c777a1f8aac5e661273bb9dd320289" - integrity sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ== - dependencies: - safe-buffer "^5.1.1" - buffer@4.9.2: version "4.9.2" resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" @@ -8741,7 +5902,7 @@ buffer@6.0.3, buffer@^6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" -buffer@^5.0.5, buffer@^5.2.1, buffer@^5.4.3, buffer@^5.5.0, buffer@^5.6.0: +buffer@^5.0.5, buffer@^5.4.3, buffer@^5.5.0, buffer@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -8790,13 +5951,6 @@ builtins@^5.0.0: dependencies: semver "^7.0.0" -bundle-require@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bundle-require/-/bundle-require-3.1.2.tgz#1374a7bdcb8b330a7ccc862ccbf7c137cc43ad27" - integrity sha512-Of6l6JBAxiyQ5axFxUM6dYeP/W7X2Sozeo/4EYB9sJhL+dqL7TKjg+shwxp6jlu/6ZSERfsYtIpSJ1/x3XkAEA== - dependencies: - load-tsconfig "^0.2.0" - bunyan-debug-stream@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/bunyan-debug-stream/-/bunyan-debug-stream-2.0.0.tgz#b9593e38753f594e3f9db3eb2fdebdc2af147a9f" @@ -8805,29 +5959,11 @@ bunyan-debug-stream@2.0.0: colors "^1.0.3" exception-formatter "^1.0.4" -bunyan-debug-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/bunyan-debug-stream/-/bunyan-debug-stream-2.0.1.tgz#9bd7c7e30c7b2cf711317e9d37529b0464c3b164" - integrity sha512-MCEoqggU7NMt7f2O+PU8VkqfSkoQoa4lmN/OWhaRfqFRBF1Se2TOXQyLF6NxC+EtfrdthnquQe8jOe83fpEoGA== - dependencies: - colors "1.4.0" - exception-formatter "^1.0.4" - bunyan-gke-stackdriver@0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/bunyan-gke-stackdriver/-/bunyan-gke-stackdriver-0.1.2.tgz#a47e3724bbb324b1ec0b7dc4350c4d7073aae66d" integrity sha512-eY5OLgAXvOvOq2YpxI0HlV5HjAcLm36Ln3PxxsztO+2GrFSgU3oXoic2LCif/heBKoyOZdMyXKWF5dvswSOS6w== -bunyan@1.8.12: - version "1.8.12" - resolved "https://registry.yarnpkg.com/bunyan/-/bunyan-1.8.12.tgz#f150f0f6748abdd72aeae84f04403be2ef113797" - integrity sha512-dmDUbGHeGcvCDLRFOscZkwx1ZO/aFz3bJOCi5nCgzdhFGPxwK+y5AcDBnqagNGlJZ7lje/l6JUEz9mQcutttdg== - optionalDependencies: - dtrace-provider "~0.8" - moment "^2.10.6" - mv "~2" - safe-json-stringify "~1" - bunyan@1.8.15: version "1.8.15" resolved "https://registry.yarnpkg.com/bunyan/-/bunyan-1.8.15.tgz#8ce34ca908a17d0776576ca1b2f6cbd916e93b46" @@ -8843,23 +5979,11 @@ byte-size@^7.0.0: resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-7.0.1.tgz#b1daf3386de7ab9d706b941a748dbfc71130dee3" integrity sha512-crQdqyCwhokxwV1UyDzLZanhkugAgft7vt0qbbdt60C6Zf3CAiGmtUCylbtYwrU6loOUw3euGrNtW1J651ot1A== -bytebuffer@~5: - version "5.0.1" - resolved "https://registry.yarnpkg.com/bytebuffer/-/bytebuffer-5.0.1.tgz#582eea4b1a873b6d020a48d58df85f0bba6cfddd" - integrity sha512-IuzSdmADppkZ6DlpycMkm8l9zeEq16fWtLvunEwFiYciR/BHo4E8/xs5piFquG+Za8OWmMqHF8zuRviz2LHvRQ== - dependencies: - long "~3" - bytes@3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== -cac@^6.7.12: - version "6.7.14" - resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" - integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== - cacache@^16.0.0, cacache@^16.0.6, cacache@^16.1.0: version "16.1.3" resolved "https://registry.yarnpkg.com/cacache/-/cacache-16.1.3.tgz#a02b9f34ecfaf9a78c9f4bc16fceb94d5d67a38e" @@ -8909,19 +6033,6 @@ cacheable-lookup@^6.0.4: resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-6.1.0.tgz#0330a543471c61faa4e9035db583aad753b36385" integrity sha512-KJ/Dmo1lDDhmW2XDPMo+9oiy/CeqosPguPCrgcVzKyZrL6pM1gU2GmPY/xo6OQPTUaA/c0kwHuywB4E6nmT9ww== -cacheable-request@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" - integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== - dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^3.0.0" - lowercase-keys "^2.0.0" - normalize-url "^4.1.0" - responselike "^1.0.2" - cacheable-request@^7.0.2: version "7.0.2" resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.2.tgz#ea0d0b889364a25854757301ca12b2da77f91d27" @@ -8935,7 +6046,7 @@ cacheable-request@^7.0.2: normalize-url "^6.0.1" responselike "^2.0.0" -call-bind@^1.0.0, call-bind@^1.0.2, call-bind@~1.0.2: +call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== @@ -8957,25 +6068,6 @@ call-me-maybe@^1.0.1: resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.2.tgz#03f964f19522ba643b1b0693acb9152fe2074baa" integrity sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ== -caller-callsite@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" - integrity sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ== - dependencies: - callsites "^2.0.0" - -caller-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" - integrity sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A== - dependencies: - caller-callsite "^2.0.0" - -callsites@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" - integrity sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ== - callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -8989,14 +6081,6 @@ camel-case@^3.0.0: no-case "^2.2.0" upper-case "^1.1.1" -camel-case@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" - integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== - dependencies: - pascal-case "^3.1.2" - tslib "^2.0.3" - camelcase-keys@^6.2.2: version "6.2.2" resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0" @@ -9006,11 +6090,6 @@ camelcase-keys@^6.2.2: map-obj "^4.0.0" quick-lru "^4.0.1" -camelcase@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" - integrity sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw== - camelcase@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" @@ -9026,7 +6105,7 @@ camelcase@^5.0.0, camelcase@^5.3.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -camelcase@^6.0.0, camelcase@^6.2.0: +camelcase@^6.2.0: version "6.3.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== @@ -9036,15 +6115,6 @@ caniuse-lite@^1.0.30001449: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001481.tgz#f58a717afe92f9e69d0e35ff64df596bfad93912" integrity sha512-KCqHwRnaa1InZBtqXzP98LPg0ajCVujMKjqKDhZEthIpAsJl/YEIa3YvXjGXPVqzZVguccuu7ga9KOE1J9rKPQ== -capital-case@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/capital-case/-/capital-case-1.0.4.tgz#9d130292353c9249f6b00fa5852bee38a717e669" - integrity sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A== - dependencies: - no-case "^3.0.4" - tslib "^2.0.3" - upper-case-first "^2.0.2" - cardinal@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/cardinal/-/cardinal-2.1.1.tgz#7cc1055d822d212954d07b085dea251cc7bc5505" @@ -9058,36 +6128,16 @@ case@^1.6.3: resolved "https://registry.yarnpkg.com/case/-/case-1.6.3.tgz#0a4386e3e9825351ca2e6216c60467ff5f1ea1c9" integrity sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ== -caseless@^0.12.0, caseless@~0.12.0: +caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== -catering@^2.0.0, catering@^2.1.0, catering@^2.1.1: +catering@^2.0.0, catering@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/catering/-/catering-2.1.1.tgz#66acba06ed5ee28d5286133982a927de9a04b510" integrity sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w== -caw@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/caw/-/caw-1.2.0.tgz#ffb226fe7efc547288dc62ee3e97073c212d1034" - integrity sha512-GIAlMoessjWW8p0mkStU4kMvV35toVCAyOWhUajk7O0d7wJI8F9TDjfrkSoO26b0d1QsnDLmw5I3X+yd6OKorQ== - dependencies: - get-proxy "^1.0.1" - is-obj "^1.0.0" - object-assign "^3.0.0" - tunnel-agent "^0.4.0" - -cbor@^4.1.5: - version "4.3.0" - resolved "https://registry.yarnpkg.com/cbor/-/cbor-4.3.0.tgz#0217c1cadd067d9112f44336dca07e72020bb804" - integrity sha512-CvzaxQlaJVa88sdtTWvLJ++MbdtPHtZOBBNjm7h3YKUHILMs9nQyD4AC6hvFZy7GBVB3I6bRibJcxeHydyT2IQ== - dependencies: - bignumber.js "^9.0.0" - commander "^3.0.0" - json-text-sequence "^0.1" - nofilter "^1.0.3" - cbor@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/cbor/-/cbor-5.2.0.tgz#4cca67783ccd6de7b50ab4ed62636712f287a67c" @@ -9096,37 +6146,7 @@ cbor@^5.2.0: bignumber.js "^9.0.1" nofilter "^1.0.4" -chai-as-promised@^7.1.0, chai-as-promised@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-7.1.1.tgz#08645d825deb8696ee61725dbf590c012eb00ca0" - integrity sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA== - dependencies: - check-error "^1.0.2" - -chai-bignumber@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/chai-bignumber/-/chai-bignumber-3.1.0.tgz#e196456c760df21f0e124f6df922289ea15a7e4c" - integrity sha512-omxEc80jAU+pZwRmoWr3aEzeLad4JW3iBhLRQlgISvghBdIxrMT7mVAGsDz4WSyCkKowENshH2j9OABAhld7QQ== - -chai-subset@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/chai-subset/-/chai-subset-1.6.0.tgz#a5d0ca14e329a79596ed70058b6646bd6988cfe9" - integrity sha512-K3d+KmqdS5XKW5DWPd5sgNffL3uxdDe+6GdnJh3AYPhwnBGRY5urfvfcbRtWIvvpz+KxkL9FeBB6MZewLUNwug== - -chai@^4.0.1, chai@^4.3.6, chai@^4.3.7: - version "4.3.7" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51" - integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A== - dependencies: - assertion-error "^1.1.0" - check-error "^1.0.2" - deep-eql "^4.1.2" - get-func-name "^2.0.0" - loupe "^2.3.1" - pathval "^1.1.1" - type-detect "^4.0.5" - -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -9151,11 +6171,6 @@ chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^5.0.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" - integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== - change-case@3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/change-case/-/change-case-3.0.2.tgz#fd48746cce02f03f0a672577d1d3a8dc2eceb037" @@ -9180,24 +6195,6 @@ change-case@3.0.2: upper-case "^1.1.1" upper-case-first "^1.1.0" -change-case@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/change-case/-/change-case-4.1.2.tgz#fedfc5f136045e2398c0410ee441f95704641e12" - integrity sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A== - dependencies: - camel-case "^4.1.2" - capital-case "^1.0.4" - constant-case "^3.0.4" - dot-case "^3.0.4" - header-case "^2.0.4" - no-case "^3.0.4" - param-case "^3.0.4" - pascal-case "^3.1.2" - path-case "^3.0.4" - sentence-case "^3.0.4" - snake-case "^3.0.4" - tslib "^2.0.3" - char-regex@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" @@ -9208,23 +6205,6 @@ chardet@^0.7.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== -"charenc@>= 0.0.1": - version "0.0.2" - resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" - integrity sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA== - -check-error@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" - integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== - -checkpoint-store@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/checkpoint-store/-/checkpoint-store-1.1.0.tgz#04e4cb516b91433893581e6d4601a78e9552ea06" - integrity sha512-J/NdY2WvIx654cc6LWSq/IYFFCUf75fFTgwzFnmbqyORH4MwgiQCgswLLKBGzmsyTI5V7i5bp/So6sMbDWhedg== - dependencies: - functional-red-black-tree "^1.0.1" - cheerio-select@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-2.1.0.tgz#4d8673286b8126ca2a8e42740d5e3c4884ae21b4" @@ -9250,51 +6230,6 @@ cheerio@^1.0.0-rc.2: parse5 "^7.0.0" parse5-htmlparser2-tree-adapter "^7.0.0" -chokidar@3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.0.tgz#12c0714668c55800f659e262d4962a97faf554a6" - integrity sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A== - dependencies: - anymatch "~3.1.1" - braces "~3.0.2" - glob-parent "~5.1.0" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.2.0" - optionalDependencies: - fsevents "~2.1.1" - -chokidar@3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.1.tgz#c84e5b3d18d9a4d77558fef466b1bf16bbeb3450" - integrity sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg== - dependencies: - anymatch "~3.1.1" - braces "~3.0.2" - glob-parent "~5.1.0" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.3.0" - optionalDependencies: - fsevents "~2.1.2" - -chokidar@3.5.3, chokidar@^3.0.2, chokidar@^3.5.3: - version "3.5.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - chownr@^1.0.1, chownr@^1.1.1, chownr@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" @@ -9339,11 +6274,6 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: inherits "^2.0.1" safe-buffer "^5.0.1" -circular@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/circular/-/circular-1.0.5.tgz#7da77af98bbde9ce4b5b358cd556b5dded2d3149" - integrity sha512-n4Sspha+wxUl5zeA3JYp1zFCjsLz2VfXIe2gRKNQBrIX+7iPdGcCGZOF8W8IULtllZ/aejXtySfdFFt1wy/3JQ== - cjs-module-lexer@^1.0.0: version "1.2.2" resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40" @@ -9369,17 +6299,6 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -classic-level@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/classic-level/-/classic-level-1.3.0.tgz#5e36680e01dc6b271775c093f2150844c5edd5c8" - integrity sha512-iwFAJQYtqRTRM0F6L8h4JCt00ZSGdOyqh7yVrhhjrOpFhmBjNlRUey64MCiyo6UmQHMJ+No3c81nujPv+n9yrg== - dependencies: - abstract-level "^1.0.2" - catering "^2.1.0" - module-error "^1.0.1" - napi-macros "^2.2.2" - node-gyp-build "^4.3.0" - clean-stack@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" @@ -9392,35 +6311,13 @@ clean-stack@^3.0.0: dependencies: escape-string-regexp "4.0.0" -cli-cursor@3.1.0, cli-cursor@^3.0.0, cli-cursor@^3.1.0: +cli-cursor@3.1.0, cli-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== dependencies: restore-cursor "^3.1.0" -cli-cursor@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" - integrity sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw== - dependencies: - restore-cursor "^2.0.0" - -cli-cursor@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-4.0.0.tgz#3cecfe3734bf4fe02a8361cbdc0f6fe28c6a57ea" - integrity sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg== - dependencies: - restore-cursor "^4.0.0" - -cli-logger@^0.5.40: - version "0.5.40" - resolved "https://registry.yarnpkg.com/cli-logger/-/cli-logger-0.5.40.tgz#097f0e11b072c7c698a26c47f588a29c20b48b0b" - integrity sha512-piXVCa0TLm/+A7xdVEhw7t4OSrsmJaZIekWcoGrVMY1bHtLJTXgiNzgHlKT0EVHQ14sCKWorQJazU7UWgZhXOQ== - dependencies: - circular "^1.0.5" - cli-util "~1.1.27" - cli-progress@^3.4.0: version "3.12.0" resolved "https://registry.yarnpkg.com/cli-progress/-/cli-progress-3.12.0.tgz#807ee14b66bcc086258e444ad0f19e7d42577942" @@ -9428,36 +6325,16 @@ cli-progress@^3.4.0: dependencies: string-width "^4.2.3" -cli-regexp@~0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/cli-regexp/-/cli-regexp-0.1.2.tgz#6bcd93b09fb2ed1025d30a1155d5997954a53512" - integrity sha512-L++cAQ5g0Nu6aV56B3uaR+c7jEGSAa4WApY1ZN7XiD8niJ5jRfXE/qvMwgz3uZBG0rft4hJS75Vpz2F3mSm4Mg== - cli-spinners@2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.6.1.tgz#adc954ebe281c37a6319bfa401e6dd2488ffb70d" integrity sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g== -cli-spinners@^2.0.0, cli-spinners@^2.5.0: +cli-spinners@^2.5.0: version "2.8.0" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.8.0.tgz#e97a3e2bd00e6d85aa0c13d7f9e3ce236f7787fc" integrity sha512-/eG5sJcvEIwxcdYM86k5tPwn0MUzkX5YY3eImTGpJOZgVe4SdTMY14vQpcxgBzJ0wXwAYrS8E+c3uHeK4JNyzQ== -cli-spinners@^2.6.1: - version "2.9.1" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.1.tgz#9c0b9dad69a6d47cbb4333c14319b060ed395a35" - integrity sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ== - -cli-table3@^0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202" - integrity sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw== - dependencies: - object-assign "^4.1.0" - string-width "^2.1.1" - optionalDependencies: - colors "^1.1.2" - cli-table@^0.3.1: version "0.3.11" resolved "https://registry.yarnpkg.com/cli-table/-/cli-table-0.3.11.tgz#ac69cdecbe81dccdba4889b9a18b7da312a9d3ee" @@ -9465,13 +6342,6 @@ cli-table@^0.3.1: dependencies: colors "1.0.3" -cli-util@~1.1.27: - version "1.1.27" - resolved "https://registry.yarnpkg.com/cli-util/-/cli-util-1.1.27.tgz#42d69e36a040a321fc9cf851c1513cadc5093054" - integrity sha512-Z6+zI0kIrqf9Oi+PmUm8J9AELp8bTf2vCLYseudYtdOPNJvzpNiExO95aHIm477IbPdu/8SE9Wvc/M1kJl4Anw== - dependencies: - cli-regexp "~0.1.0" - cli-ux@5.6.6: version "5.6.6" resolved "https://registry.yarnpkg.com/cli-ux/-/cli-ux-5.6.6.tgz#1424f5a9fbddcd796ad985b867a3de7f5a452090" @@ -9563,17 +6433,12 @@ cli-ux@^4.4.0: treeify "^1.1.0" tslib "^1.9.3" -cli-width@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" - integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== - cli-width@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== -cliui@^3.0.3, cliui@^3.2.0: +cliui@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" integrity sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w== @@ -9627,11 +6492,6 @@ cliui@^8.0.1: strip-ansi "^6.0.1" wrap-ansi "^7.0.0" -clone-buffer@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" - integrity sha512-KLLTJWrvwIP+OPfMn0x2PheDEP20RPUcGXj/ERegTgdmPEZylALQldygiqrPPu8P45uNuPs7ckmReLY6v/iA5g== - clone-deep@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" @@ -9653,11 +6513,6 @@ clone@^1.0.2: resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== -clone@^2.0.0, clone@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" - integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w== - cmd-shim@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-5.0.0.tgz#8d0aaa1a6b0708630694c4dbde070ed94c707724" @@ -9670,11 +6525,6 @@ co@^4.6.0: resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== -code-error-fragment@0.0.230: - version "0.0.230" - resolved "https://registry.yarnpkg.com/code-error-fragment/-/code-error-fragment-0.0.230.tgz#d736d75c832445342eca1d1fedbf17d9618b14d7" - integrity sha512-cadkfKp6932H8UkhzE/gcUqhRMNf8jHzkAN7+5Myabswaghu4xABTgPHDCjW+dBAJxj/SpkTYokpzDqY4pCzQw== - code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" @@ -9691,14 +6541,6 @@ codecov@^3.6.5: teeny-request "7.1.1" urlgrey "1.0.0" -coinstring@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/coinstring/-/coinstring-2.3.0.tgz#cdb63363a961502404a25afb82c2e26d5ff627a4" - integrity sha512-2xMhQ++4ETUPiy2oqOlfydsuQArNLB6TExNF33Jmv+IgpmV8Hf6v6yICQAwH4uEHTnkJ3DscSyeKFrg37ljIOw== - dependencies: - bs58 "^2.0.1" - create-hash "^1.1.1" - collect-v8-coverage@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" @@ -9751,11 +6593,6 @@ colors@1.4.0, colors@^1.0.3, colors@^1.1.2: resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== -colour@~0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/colour/-/colour-0.7.1.tgz#9cb169917ec5d12c0736d3e8685746df1cadf778" - integrity sha512-Rel466v0EnmKPcsxHo91L4kgPs/6XF7Pu2LJNszq9lXYwi5CFWEeIiRaTX5ym7PPMdj4udDHkLSVC1//JVkZQg== - columnify@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.6.0.tgz#6989531713c9008bb29735e61e37acf5bd553cf3" @@ -9776,55 +6613,21 @@ command-exists@^1.2.8, command-exists@^1.2.9: resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== -command-line-args@^4.0.7: - version "4.0.7" - resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-4.0.7.tgz#f8d1916ecb90e9e121eda6428e41300bfb64cc46" - integrity sha512-aUdPvQRAyBvQd2n7jXcsMDz68ckBJELXNzBybCHOibUWEg0mWTnaYCSRU8h9R+aNRSvDihJtssSRCiDRpLaezA== - dependencies: - array-back "^2.0.0" - find-replace "^1.0.3" - typical "^2.6.1" - -commander@2.15.1: - version "2.15.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" - integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== - -commander@2.18.0: - version "2.18.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970" - integrity sha512-6CYPa+JP2ftfRU2qkDK+UTVeQYosOg/2GbcjIcKPHfinyOLPVGXu/ovN86RP49Re5ndJK1N0kuiidFFuepc4ZQ== - -commander@3.0.2, commander@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" - integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== - commander@^10.0.0: version "10.0.1" resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== -commander@^2.12.1, commander@^2.20.3, commander@^2.8.1: +commander@^2.12.1: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== -commander@^8.1.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" - integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== - common-ancestor-path@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz#4f7d2d1394d91b7abdf51871c62f71eadb0182a7" integrity sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w== -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== - compare-func@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-2.0.0.tgz#fb65e75edbddfd2e568554e8b5b05fff7a51fcb3" @@ -9833,43 +6636,16 @@ compare-func@^2.0.0: array-ify "^1.0.0" dot-prop "^5.1.0" -compare-versions@^3.5.1: - version "3.6.0" - resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.6.0.tgz#1a5689913685e5a87637b8d3ffca75514ec41d62" - integrity sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA== - -complex.js@2.0.11: - version "2.0.11" - resolved "https://registry.yarnpkg.com/complex.js/-/complex.js-2.0.11.tgz#09a873fbf15ffd8c18c9c2201ccef425c32b8bf1" - integrity sha512-6IArJLApNtdg1P1dFtn3dnyzoZBEF0MwMnrfF1exSBRpZYoy4yieMkpZhQDC0uwctw48vii0CFVyHfpgZ/DfGw== - -component-emitter@^1.2.0, component-emitter@^1.2.1: +component-emitter@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== -compressible@^2.0.12: - version "2.0.18" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" - integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== - dependencies: - mime-db ">= 1.43.0 < 2" - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== -concat-stream@^1.6.0, concat-stream@^1.6.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - concat-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-2.0.0.tgz#414cf5af790a48c60ab9be4527d56d5e41133cb1" @@ -9880,22 +6656,6 @@ concat-stream@^2.0.0: readable-stream "^3.0.2" typedarray "^0.0.6" -conf@^10.1.2: - version "10.2.0" - resolved "https://registry.yarnpkg.com/conf/-/conf-10.2.0.tgz#838e757be963f1a2386dfe048a98f8f69f7b55d6" - integrity sha512-8fLl9F04EJqjSqH+QjITQfJF8BrOVaYr1jewVgSRAEWePfxT0sku4w2hrGQ60BC/TNLGQ2pgxNlTbWQmMPFvXg== - dependencies: - ajv "^8.6.3" - ajv-formats "^2.1.1" - atomically "^1.7.0" - debounce-fn "^4.0.0" - dot-prop "^6.0.1" - env-paths "^2.2.1" - json-schema-typed "^7.0.3" - onetime "^5.1.2" - pkg-up "^3.1.0" - semver "^7.3.5" - config-chain@^1.1.12: version "1.1.13" resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.13.tgz#fad0795aa6a6cdaff9ed1b68e9dff94372c232f4" @@ -9904,19 +6664,7 @@ config-chain@^1.1.12: ini "^1.3.4" proto-list "~1.2.1" -configstore@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/configstore/-/configstore-4.0.0.tgz#5933311e95d3687efb592c528b922d9262d227e7" - integrity sha512-CmquAXFBocrzaSM8mtGPMM/HiWmyIpr4CcJl/rgY2uCObZ/S7cKU0silxslqJejl+t/T9HS8E0PUNQD81JGUEQ== - dependencies: - dot-prop "^4.1.0" - graceful-fs "^4.1.2" - make-dir "^1.0.0" - unique-string "^1.0.0" - write-file-atomic "^2.0.0" - xdg-basedir "^3.0.0" - -console-control-strings@^1.0.0, console-control-strings@^1.1.0, console-control-strings@~1.1.0: +console-control-strings@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== @@ -9929,15 +6677,6 @@ constant-case@^2.0.0: snake-case "^2.1.0" upper-case "^1.1.1" -constant-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/constant-case/-/constant-case-3.0.4.tgz#3b84a9aeaf4cf31ec45e6bf5de91bdfb0589faf1" - integrity sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ== - dependencies: - no-case "^3.0.4" - tslib "^2.0.3" - upper-case "^2.0.2" - content-disposition@0.5.4: version "0.5.4" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" @@ -10071,24 +6810,12 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw== -core-js-compat@^3.25.1: - version "3.30.1" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.30.1.tgz#961541e22db9c27fc48bfc13a3cafa8734171dfe" - integrity sha512-d690npR7MC6P0gq4npTl5n2VQeNAmUrJ90n+MHiKS7W2+xno4o3F5GDEuylSdi6EJ3VssibSGXOa1r3YXD3Mhw== - dependencies: - browserslist "^4.21.5" - -core-js-pure@^3.0.1: - version "3.30.1" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.30.1.tgz#7d93dc89e7d47b8ef05d7e79f507b0e99ea77eec" - integrity sha512-nXBEVpmUnNRhz83cHd9JRQC52cTMcuXAmR56+9dSMpRdpeA4I1PX6yjmhd71Eyc/wXNsdBdUDIj1QTIeZpU5Tg== - core-js@^2.4.0: version "2.6.12" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== -core-js@^3.0.0, core-js@^3.2.1: +core-js@^3.0.0: version "3.30.1" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.30.1.tgz#fc9c5adcc541d8e9fa3e381179433cbf795628ba" integrity sha512-ZNS5nbiSwDTq4hFosEDqm65izl2CWmLz0hARJMyNQBgkUZMIF51cQiMvIQKA6hvuaeWxQDP3hEedM1JZIgTldQ== @@ -10103,7 +6830,7 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== -cors@^2.8.1, cors@^2.8.5: +cors@^2.8.1: version "2.8.5" resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== @@ -10111,16 +6838,6 @@ cors@^2.8.1, cors@^2.8.5: object-assign "^4" vary "^1" -cosmiconfig@^5.0.7: - version "5.2.1" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" - integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== - dependencies: - import-fresh "^2.0.0" - is-directory "^0.3.1" - js-yaml "^3.13.1" - parse-json "^4.0.0" - cosmiconfig@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6" @@ -10145,15 +6862,7 @@ crc-32@^1.2.0: resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== -create-ecdh@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" - integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== - dependencies: - bn.js "^4.1.0" - elliptic "^6.5.3" - -create-hash@^1.1.0, create-hash@^1.1.1, create-hash@^1.1.2, create-hash@^1.2.0: +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== @@ -10164,7 +6873,7 @@ create-hash@^1.1.0, create-hash@^1.1.1, create-hash@^1.1.2, create-hash@^1.2.0: ripemd160 "^2.0.1" sha.js "^2.4.0" -create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: +create-hmac@^1.1.4, create-hmac@^1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== @@ -10181,13 +6890,6 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== -cross-env@^5.1.6: - version "5.2.1" - resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-5.2.1.tgz#b2c76c1ca7add66dc874d11798466094f551b34d" - integrity sha512-1yHhtcfAd1r4nwQgknowuUNfIT9E8dOMMspC36g45dN+iD1blloi7xp8X/xAIDnjHWyt1uQ8PHk2fkNaym7soQ== - dependencies: - cross-spawn "^6.0.5" - cross-fetch@3.0.6: version "3.0.6" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.0.6.tgz#3a4040bc8941e653e0e9cf17f29ebcd177d3365c" @@ -10238,15 +6940,10 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" -"crypt@>= 0.0.1": - version "0.0.2" - resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" - integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow== - crypto-addr-codec@^0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/crypto-addr-codec/-/crypto-addr-codec-0.1.7.tgz#e16cea892730178fe25a38f6d15b680cab3124ae" - integrity sha512-X4hzfBzNhy4mAc3UpiXEC/L0jo5E8wAa9unsnA8nNXYzXjCcGk83hfC5avJWCSGT8V91xMnAS9AKMHmjw5+XCg== + version "0.1.8" + resolved "https://registry.yarnpkg.com/crypto-addr-codec/-/crypto-addr-codec-0.1.8.tgz#45c4b24e2ebce8e24a54536ee0ca25b65787b016" + integrity sha512-GqAK90iLLgP3FvhNmHbpT3wR6dEdaM8hZyZtLX29SPardh3OA13RFLHDR6sntGCgRWOfiHqW6sIyohpNqOtV/g== dependencies: base-x "^3.0.8" big-integer "1.6.36" @@ -10256,33 +6953,6 @@ crypto-addr-codec@^0.1.7: safe-buffer "^5.2.0" sha3 "^2.1.1" -crypto-browserify@3.12.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== - dependencies: - browserify-cipher "^1.0.0" - browserify-sign "^4.0.0" - create-ecdh "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.0" - diffie-hellman "^5.0.0" - inherits "^2.0.1" - pbkdf2 "^3.0.3" - public-encrypt "^4.0.0" - randombytes "^2.0.0" - randomfill "^1.0.3" - -crypto-js@^3.1.4: - version "3.3.0" - resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.3.0.tgz#846dd1cce2f68aacfa156c8578f926a609b7976b" - integrity sha512-DIT51nX0dCfKltpRiXV+/TVZq+Qq2NgF4644+K7Ttnla7zEzqc+kjJyiB96BHNyUTBxyjzRcZYpUdZa+QAqi6Q== - -crypto-random-string@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" - integrity sha512-GsVpkFPlycH7/fRR7Dhcmnoii54gV1nz7y4CWyeFS14N+JVBBhY+r8amRHE4BwSYal7BPTDp8isvAlCxyFt3Hg== - css-select@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6" @@ -10299,16 +6969,6 @@ css-what@^6.1.0: resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== -cssfilter@0.0.10: - version "0.0.10" - resolved "https://registry.yarnpkg.com/cssfilter/-/cssfilter-0.0.10.tgz#c6d2672632a2e5c83e013e6864a42ce8defd20ae" - integrity sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw== - -csstype@^3.0.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b" - integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ== - csv-generate@^3.4.3: version "3.4.3" resolved "https://registry.yarnpkg.com/csv-generate/-/csv-generate-3.4.3.tgz#bc42d943b45aea52afa896874291da4b9108ffff" @@ -10319,21 +6979,6 @@ csv-parse@^4.16.3: resolved "https://registry.yarnpkg.com/csv-parse/-/csv-parse-4.16.3.tgz#7ca624d517212ebc520a36873c3478fa66efbaf7" integrity sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg== -csv-parser@^2.0.0: - version "2.3.5" - resolved "https://registry.yarnpkg.com/csv-parser/-/csv-parser-2.3.5.tgz#6b3bf0907684914ff2c5abfbadab111a69eae5db" - integrity sha512-LCHolC4AlNwL+5EuD5LH2VVNKpD8QixZW2zzK1XmrVYUaslFY4c5BooERHOCIubG9iv/DAyFjs4x0HvWNZuyWg== - dependencies: - minimist "^1.2.0" - through2 "^3.0.1" - -csv-stringify@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/csv-stringify/-/csv-stringify-4.3.1.tgz#7bee36f746ef555dd481a735a9e2938965f8478b" - integrity sha512-VRjPYIUzex5kfbsOY7LaJcNE2qMWGQQAanb3/Vv85WbOgA+dAfDNfwntRvv335icJgGYrnTX403WxJxRVpLDFA== - dependencies: - lodash.get "~4.4.2" - csv-stringify@^5.6.5: version "5.6.5" resolved "https://registry.yarnpkg.com/csv-stringify/-/csv-stringify-5.6.5.tgz#c6d74badda4b49a79bf4e72f91cce1e33b94de00" @@ -10384,28 +7029,11 @@ data-uri-to-buffer@^4.0.0: resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e" integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A== -dataloader@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/dataloader/-/dataloader-2.1.0.tgz#c69c538235e85e7ac6c6c444bae8ecabf5de9df7" - integrity sha512-qTcEYLen3r7ojZNgVUaRggOI+KM7jrKxXeSHhogh/TWxYMeONEMqY+hmkobiYQozsGIyg9OYVzO4ZIfoB4I0pQ== - -date-and-time@^0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/date-and-time/-/date-and-time-0.6.3.tgz#2daee52df67c28bd93bce862756ac86b68cf4237" - integrity sha512-lcWy3AXDRJOD7MplwZMmNSRM//kZtJaLz4n6D1P5z9wEmZGBKhJRBIr1Xs9KNQJmdXPblvgffynYji4iylUTcA== - dateformat@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== -debounce-fn@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/debounce-fn/-/debounce-fn-4.0.0.tgz#ed76d206d8a50e60de0dd66d494d82835ffe61c7" - integrity sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ== - dependencies: - mimic-fn "^3.0.0" - debug@2.6.9, debug@^2.2.0, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -10413,28 +7041,14 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3: dependencies: ms "2.0.0" -debug@3.1.0, debug@=3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== - dependencies: - ms "2.0.0" - -debug@3.2.6: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== - dependencies: - ms "^2.1.1" - -debug@4, debug@4.3.4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.3, debug@^4.3.4: +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.3, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" -debug@^3.1.0, debug@^3.2.6: +debug@^3.1.0: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== @@ -10459,40 +7073,18 @@ decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.2.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== -decamelize@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" - integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== - -decimal.js@10.2.0: - version "10.2.0" - resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.0.tgz#39466113a9e036111d02f82489b5fd6b0b5ed231" - integrity sha512-vDPw+rDgn3bZe1+F/pyEwb1oMG2XTlRVgAa6B4KccTEpYgF8w6eQllVbQcfIJnZyvzFtFpxnpGtx8dd7DJp/Rw== - -decimal.js@^10.0.0: - version "10.4.3" - resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" - integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== - decode-uri-component@^0.2.0: version "0.2.2" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== -decompress-response@^3.2.0, decompress-response@^3.3.0: +decompress-response@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" integrity sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA== dependencies: mimic-response "^1.0.0" -decompress-response@^4.2.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986" - integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw== - dependencies: - mimic-response "^2.0.0" - decompress-response@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" @@ -10500,93 +7092,16 @@ decompress-response@^6.0.0: dependencies: mimic-response "^3.1.0" -decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" - integrity sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ== - dependencies: - file-type "^5.2.0" - is-stream "^1.1.0" - tar-stream "^1.5.2" - -decompress-tarbz2@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" - integrity sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A== - dependencies: - decompress-tar "^4.1.0" - file-type "^6.1.0" - is-stream "^1.1.0" - seek-bzip "^1.0.5" - unbzip2-stream "^1.0.9" - -decompress-targz@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" - integrity sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w== - dependencies: - decompress-tar "^4.1.1" - file-type "^5.2.0" - is-stream "^1.1.0" - -decompress-unzip@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" - integrity sha512-1fqeluvxgnn86MOh66u8FjbtJpAFv5wgCT9Iw8rcBqQcCo5tO8eiJw7NNTrvt9n4CRBVq7CstiS922oPgyGLrw== - dependencies: - file-type "^3.8.0" - get-stream "^2.2.0" - pify "^2.3.0" - yauzl "^2.4.2" - -decompress@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.1.tgz#007f55cc6a62c055afa37c07eb6a4ee1b773f118" - integrity sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ== - dependencies: - decompress-tar "^4.0.0" - decompress-tarbz2 "^4.0.0" - decompress-targz "^4.0.0" - decompress-unzip "^4.0.1" - graceful-fs "^4.1.10" - make-dir "^1.0.0" - pify "^2.3.0" - strip-dirs "^2.0.0" - dedent@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== -deep-eql@^4.1.2: - version "4.1.3" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" - integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== - dependencies: - type-detect "^4.0.0" - -deep-equal@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" - integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== - dependencies: - is-arguments "^1.0.4" - is-date-object "^1.0.1" - is-regex "^1.0.4" - object-is "^1.0.1" - object-keys "^1.1.1" - regexp.prototype.flags "^1.2.0" - deep-extend@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== -deep-is@~0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - deepmerge@^4.2.2: version "4.3.1" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" @@ -10599,39 +7114,11 @@ defaults@^1.0.3: dependencies: clone "^1.0.2" -defer-to-connect@^1.0.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" - integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== - defer-to-connect@^2.0.0, defer-to-connect@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== -deferred-leveldown@~1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz#3acd2e0b75d1669924bc0a4b642851131173e1eb" - integrity sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA== - dependencies: - abstract-leveldown "~2.6.0" - -deferred-leveldown@~4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz#0b0570087827bf480a23494b398f04c128c19a20" - integrity sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww== - dependencies: - abstract-leveldown "~5.0.0" - inherits "^2.0.3" - -deferred-leveldown@~5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-5.3.0.tgz#27a997ad95408b61161aa69bd489b86c71b78058" - integrity sha512-a59VOT+oDy7vtAbLRCZwWgxu2BaCfd5Hk7wxJd48ei7I+nsg8Orlb9CLG0PMZienk9BSUKgeAqkO2+Lw+1+Ukw== - dependencies: - abstract-leveldown "~6.2.1" - inherits "^2.0.3" - define-data-property@^1.0.1, define-data-property@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" @@ -10646,7 +7133,7 @@ define-lazy-prop@^2.0.0: resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== -define-properties@^1.1.2, define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0: +define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== @@ -10676,16 +7163,6 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" -defined@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.1.tgz#c0b9db27bfaffd95d6f61399419b893df0f91ebf" - integrity sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q== - -delay@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/delay/-/delay-5.0.0.tgz#137045ef1b96e5071060dd5be60bf9334436bd1d" - integrity sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw== - delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -10696,46 +7173,21 @@ delegates@^1.0.0: resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== -delimit-stream@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/delimit-stream/-/delimit-stream-0.1.0.tgz#9b8319477c0e5f8aeb3ce357ae305fc25ea1cd2b" - integrity sha512-a02fiQ7poS5CnjiJBAsjGLPp5EwVoGHNeu9sziBd9huppRfsAFIpv5zNLv0V1gbop53ilngAf5Kf331AwcoRBQ== - depd@2.0.0, depd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== - deprecation@^2.0.0, deprecation@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== -des.js@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" - integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== - dependencies: - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - destroy@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== -detect-file@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-0.1.0.tgz#4935dedfd9488648e006b0129566e9386711ea63" - integrity sha512-akiVcMZym+vO3IxctGG9dnuJT4AYQTAhjsGbjeGqqMUr9Ffy7XEAUmfKLSHugr/tGLaAZ4jWROErPPrsfG8+bQ== - dependencies: - fs-exists-sync "^0.1.0" - detect-indent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" @@ -10746,18 +7198,6 @@ detect-indent@^6.0.0: resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.1.0.tgz#592485ebbbf6b3b1ab2be175c8393d04ca0d57e6" integrity sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA== -detect-installed@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/detect-installed/-/detect-installed-2.0.4.tgz#a0850465e7c3ebcff979d6b6535ad344b80dd7c5" - integrity sha512-IpGo06Ff/rMGTKjFvVPbY9aE4mRT2XP3eYHC/ZS25LKDr2h8Gbv74Ez2q/qd7IYDqD9ZjI/VGedHNXsbKZ/Eig== - dependencies: - get-installed-path "^2.0.3" - -detect-libc@^1.0.2, detect-libc@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== - detect-libc@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.1.tgz#e1897aa88fa6ad197862937fbc0441ef352ee0cd" @@ -10768,18 +7208,6 @@ detect-newline@^3.0.0: resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== -detect-node@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.3.tgz#a2033c09cc8e158d37748fbde7507832bd6ce127" - integrity sha512-64uDTOK+fKEa6XoSbkkDoeAX8Ep1XhwxwZtL1aw1En5p5UOK/ekJoFqd5BB1o+uOvF1iHVv6qDUxdOQ/VgWEQg== - -detect-package-manager@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/detect-package-manager/-/detect-package-manager-2.0.1.tgz#6b182e3ae5e1826752bfef1de9a7b828cffa50d8" - integrity sha512-j/lJHyoLlWi6G1LDdLgvUtz60Zo5GEj+sVYtTVXnYLDPuzgC3llMxonXym9zIwhhUII8vjdw0LXxavpLqTbl1A== - dependencies: - execa "^5.1.1" - dezalgo@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.4.tgz#751235260469084c132157dfa857f386d4c33d81" @@ -10793,30 +7221,11 @@ diff-sequences@^29.4.3: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.4.3.tgz#9314bc1fabe09267ffeca9cbafc457d8499a13f2" integrity sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA== -diff@3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" - integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== - -diff@4.0.2, diff@^4.0.1: +diff@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== -diff@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" - integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== - -diffie-hellman@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== - dependencies: - bn.js "^4.1.0" - miller-rabin "^4.0.0" - randombytes "^2.0.0" - dijkstrajs@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/dijkstrajs/-/dijkstrajs-1.0.3.tgz#4c8dbdea1f0f6478bff94d9c49c784d623e4fc23" @@ -10837,16 +7246,6 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" -dir-to-object@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/dir-to-object/-/dir-to-object-2.0.0.tgz#29723e9bd1c3e58e4f307bd04ff634c0370c8f8a" - integrity sha512-sXs0JKIhymON7T1UZuO2Ud6VTNAx/VTBXIl4+3mjb2RgfOpt+hectX0x04YqPOPdkeOAKoJuKqwqnXXURNPNEA== - -dirty-chai@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/dirty-chai/-/dirty-chai-2.0.1.tgz#6b2162ef17f7943589da840abc96e75bda01aff3" - integrity sha512-ys79pWKvDMowIDEPC6Fig8d5THiC0DJ2gmTeGzVAoEH18J8OzLud0Jh7I9IWg3NSk8x2UocznUuFmfHCXYZx9w== - doctrine@0.7.2: version "0.7.2" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-0.7.2.tgz#7cb860359ba3be90e040b26b729ce4bfa654c523" @@ -10855,13 +7254,6 @@ doctrine@0.7.2: esutils "^1.1.6" isarray "0.0.1" -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - dom-serializer@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" @@ -10881,7 +7273,7 @@ domelementtype@^2.3.0: resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== -domhandler@^5.0.1, domhandler@^5.0.2, domhandler@^5.0.3: +domhandler@^5.0.2, domhandler@^5.0.3: version "5.0.3" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== @@ -10889,13 +7281,13 @@ domhandler@^5.0.1, domhandler@^5.0.2, domhandler@^5.0.3: domelementtype "^2.3.0" domutils@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.0.1.tgz#696b3875238338cb186b6c0612bd4901c89a4f1c" - integrity sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q== + version "3.1.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e" + integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA== dependencies: dom-serializer "^2.0.0" domelementtype "^2.3.0" - domhandler "^5.0.1" + domhandler "^5.0.3" dot-case@^2.1.0: version "2.1.1" @@ -10904,21 +7296,6 @@ dot-case@^2.1.0: dependencies: no-case "^2.2.0" -dot-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" - integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== - dependencies: - no-case "^3.0.4" - tslib "^2.0.3" - -dot-prop@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.1.tgz#45884194a71fc2cda71cbb4bceb3a4dd2f433ba4" - integrity sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ== - dependencies: - is-obj "^1.0.0" - dot-prop@^5.1.0: version "5.3.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" @@ -10933,26 +7310,6 @@ dot-prop@^6.0.1: dependencies: is-obj "^2.0.0" -dotdir-regex@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/dotdir-regex/-/dotdir-regex-0.1.0.tgz#d45df4c8863be6f5593d716914381767e938c0b6" - integrity sha512-00odj/E9hnwoi/W0ZcudUwlR/OSjhMgcBgevA4G8tgSJdGy0cVIKrmKLkh97Kw6aXvE47islrIisBld19+X1AQ== - -dotenv-expand@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-10.0.0.tgz#12605d00fb0af6d0a592e6558585784032e4ef37" - integrity sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A== - -dotenv@*, dotenv@^16.0.3: - version "16.0.3" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" - integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== - -dotenv@8.2.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a" - integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw== - dotenv@^8.2.0: version "8.6.0" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b" @@ -10963,27 +7320,6 @@ dotenv@~10.0.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== -dotignore@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/dotignore/-/dotignore-0.1.2.tgz#f942f2200d28c3a76fbdd6f0ee9f3257c8a2e905" - integrity sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw== - dependencies: - minimatch "^3.0.4" - -double-ended-queue@2.1.0-0: - version "2.1.0-0" - resolved "https://registry.yarnpkg.com/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz#103d3527fd31528f40188130c841efdd78264e5c" - integrity sha512-+BNfZ+deCo8hMNpDqDnvT+c0XpJ5cUa6mqYq89bho2Ifze4URTqRkcwR399hWoTrTkbZ/XJYDgP6rc7pRgffEQ== - -drbg.js@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/drbg.js/-/drbg.js-1.0.1.tgz#3e36b6c42b37043823cdbc332d58f31e2445480b" - integrity sha512-F4wZ06PvqxYLFEZKkFxTDcns9oFNk34hvmJSEwdzsxVQ8YI5YaxtACgQatkYgv2VI2CFkUd2Y+xosPQnHv809g== - dependencies: - browserify-aes "^1.0.6" - create-hash "^1.1.2" - create-hmac "^1.1.4" - dtrace-provider@~0.8: version "0.8.8" resolved "https://registry.yarnpkg.com/dtrace-provider/-/dtrace-provider-0.8.8.tgz#2996d5490c37e1347be263b423ed7b297fb0d97e" @@ -10991,26 +7327,11 @@ dtrace-provider@~0.8: dependencies: nan "^2.14.0" -duplexer3@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e" - integrity sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA== - duplexer@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= -duplexify@^3.5.0, duplexify@^3.6.0: - version "3.7.1" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" - integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== - dependencies: - end-of-stream "^1.0.0" - inherits "^2.0.1" - readable-stream "^2.0.0" - stream-shift "^1.0.0" - duplexify@^4.0.0: version "4.1.2" resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.2.tgz#18b4f8d28289132fa0b9573c898d9f903f81c7b0" @@ -11021,11 +7342,6 @@ duplexify@^4.0.0: readable-stream "^3.1.1" stream-shift "^1.0.0" -eastasianwidth@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" - integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== - ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" @@ -11041,14 +7357,6 @@ ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11: dependencies: safe-buffer "^5.0.1" -ecurve@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/ecurve/-/ecurve-1.0.6.tgz#dfdabbb7149f8d8b78816be5a7d5b83fcf6de797" - integrity sha512-/BzEjNfiSuB7jIWKcS/z8FK9jNjmEWvUV2YZ4RLSmcDtP7Lq0m6FvDuSnJpBlDpGRpfRQeTLGLBI8H+kEv0r+w== - dependencies: - bigi "^1.1.0" - safe-buffer "^5.0.1" - ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -11066,17 +7374,7 @@ electron-to-chromium@^1.4.284: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.369.tgz#a98d838cdd79be4471cd04e9b4dffe891d037874" integrity sha512-LfxbHXdA/S+qyoTEA4EbhxGjrxx7WK2h6yb5K2v0UCOufUKX+VZaHbl3svlzZfv9sGseym/g3Ne4DpsgRULmqg== -elliptic@6.3.3: - version "6.3.3" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.3.3.tgz#5482d9646d54bcb89fd7d994fc9e2e9568876e3f" - integrity sha512-cIky9SO2H8W2eU1NOLySnhOYJnuEWCq9ZJeHvHd/lXzEL9vyraIMfilZSn57X3aVX+wkfYmqkch2LvmTzkjFpA== - dependencies: - bn.js "^4.4.0" - brorand "^1.0.1" - hash.js "^1.0.0" - inherits "^2.0.1" - -elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3, elliptic@^6.5.4: +elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== @@ -11099,11 +7397,6 @@ emittery@^0.13.1: resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== -emittery@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.4.1.tgz#abe9d3297389ba424ac87e53d1c701962ce7433d" - integrity sha512-r4eRSeStEGf6M5SKdrQhhLK5bOwOBxQhIE3YSTnZE3GpKiLfnnhE+tPtrJE79+eDJgm39BM6LSoI8SCx4HbwlQ== - emoji-regex@^7.0.1: version "7.0.3" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" @@ -11114,38 +7407,12 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -emoji-regex@^9.2.2: - version "9.2.2" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" - integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== - encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== -encoding-down@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/encoding-down/-/encoding-down-6.3.0.tgz#b1c4eb0e1728c146ecaef8e32963c549e76d082b" - integrity sha512-QKrV0iKR6MZVJV08QY0wp1e7vF6QbhnbQhb07bwpEyuz4uZiZgPlEGdkCROuFkUwdxlFaiPIhjyarH1ee/3vhw== - dependencies: - abstract-leveldown "^6.2.1" - inherits "^2.0.3" - level-codec "^9.0.0" - level-errors "^2.0.0" - -encoding-down@~5.0.0: - version "5.0.4" - resolved "https://registry.yarnpkg.com/encoding-down/-/encoding-down-5.0.4.tgz#1e477da8e9e9d0f7c8293d320044f8b2cd8e9614" - integrity sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw== - dependencies: - abstract-leveldown "^5.0.0" - inherits "^2.0.3" - level-codec "^9.0.0" - level-errors "^2.0.0" - xtend "^4.0.1" - -encoding@^0.1.11, encoding@^0.1.13: +encoding@^0.1.13: version "0.1.13" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== @@ -11159,18 +7426,6 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: dependencies: once "^1.4.0" -end-stream@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/end-stream/-/end-stream-0.1.0.tgz#32003f3f438a2b0143168137f8fa6e9866c81ed5" - integrity sha512-Brl10T8kYnc75IepKizW6Y9liyW8ikz1B7n/xoHrJxoVSSjoqPn30sb7XVFfQERK4QfUMYRGs9dhWwtt2eu6uA== - dependencies: - write-stream "~0.4.3" - -ends-with@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/ends-with/-/ends-with-0.2.0.tgz#2f9da98d57a50cfda4571ce4339000500f4e6b8a" - integrity sha512-lRppY4dK3VkqBdR242sKcAJeYc8Gf/DhoX9AWvWI2RzccmLnqBQfwm2k4oSDv5MPDjUqawCauXhZkyWxkVhRsg== - enquirer@^2.3.0: version "2.4.1" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56" @@ -11186,17 +7441,12 @@ enquirer@~2.3.6: dependencies: ansi-colors "^4.1.1" -ent@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" - integrity sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA== - entities@^4.2.0, entities@^4.4.0: version "4.5.0" resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== -env-paths@^2.2.0, env-paths@^2.2.1: +env-paths@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== @@ -11211,13 +7461,6 @@ err-code@^2.0.2: resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA== -errno@~0.1.1: - version "0.1.8" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" - integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== - dependencies: - prr "~1.0.1" - error-ex@^1.2.0, error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" @@ -11240,46 +7483,6 @@ error@^7.0.0: dependencies: string-template "~0.2.1" -es-abstract@^1.17.0-next.1, es-abstract@^1.19.0, es-abstract@^1.20.4, es-abstract@^1.21.2: - version "1.21.2" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.2.tgz#a56b9695322c8a185dc25975aa3b8ec31d0e7eff" - integrity sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg== - dependencies: - array-buffer-byte-length "^1.0.0" - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - es-set-tostringtag "^2.0.1" - es-to-primitive "^1.2.1" - function.prototype.name "^1.1.5" - get-intrinsic "^1.2.0" - get-symbol-description "^1.0.0" - globalthis "^1.0.3" - gopd "^1.0.1" - has "^1.0.3" - has-property-descriptors "^1.0.0" - has-proto "^1.0.1" - has-symbols "^1.0.3" - internal-slot "^1.0.5" - is-array-buffer "^3.0.2" - is-callable "^1.2.7" - is-negative-zero "^2.0.2" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.2" - is-string "^1.0.7" - is-typed-array "^1.1.10" - is-weakref "^1.0.2" - object-inspect "^1.12.3" - object-keys "^1.1.1" - object.assign "^4.1.4" - regexp.prototype.flags "^1.4.3" - safe-regex-test "^1.0.0" - string.prototype.trim "^1.2.7" - string.prototype.trimend "^1.0.6" - string.prototype.trimstart "^1.0.6" - typed-array-length "^1.0.4" - unbox-primitive "^1.0.2" - which-typed-array "^1.1.9" - es-abstract@^1.22.1: version "1.22.3" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.3.tgz#48e79f5573198de6dee3589195727f4f74bc4f32" @@ -11325,26 +7528,6 @@ es-abstract@^1.22.1: unbox-primitive "^1.0.2" which-typed-array "^1.1.13" -es-array-method-boxes-properly@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" - integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== - -es-get-iterator@^1.0.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.3.tgz#3ef87523c5d464d41084b2c3c9c214f1199763d6" - integrity sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.3" - has-symbols "^1.0.3" - is-arguments "^1.1.1" - is-map "^2.0.2" - is-set "^2.0.2" - is-string "^1.0.7" - isarray "^2.0.5" - stop-iteration-iterator "^1.0.0" - es-set-tostringtag@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" @@ -11388,18 +7571,11 @@ es6-iterator@^2.0.3: es5-ext "^0.10.35" es6-symbol "^3.1.1" -es6-promise@^4.0.3, es6-promise@^4.2.8: +es6-promise@^4.2.8: version "4.2.8" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== -es6-promisify@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" - integrity sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ== - dependencies: - es6-promise "^4.0.3" - es6-symbol@^3.1.1, es6-symbol@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" @@ -11408,34 +7584,6 @@ es6-symbol@^3.1.1, es6-symbol@^3.1.3: d "^1.0.1" ext "^1.1.2" -esbuild@0.16.17: - version "0.16.17" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.16.17.tgz#fc2c3914c57ee750635fee71b89f615f25065259" - integrity sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg== - optionalDependencies: - "@esbuild/android-arm" "0.16.17" - "@esbuild/android-arm64" "0.16.17" - "@esbuild/android-x64" "0.16.17" - "@esbuild/darwin-arm64" "0.16.17" - "@esbuild/darwin-x64" "0.16.17" - "@esbuild/freebsd-arm64" "0.16.17" - "@esbuild/freebsd-x64" "0.16.17" - "@esbuild/linux-arm" "0.16.17" - "@esbuild/linux-arm64" "0.16.17" - "@esbuild/linux-ia32" "0.16.17" - "@esbuild/linux-loong64" "0.16.17" - "@esbuild/linux-mips64el" "0.16.17" - "@esbuild/linux-ppc64" "0.16.17" - "@esbuild/linux-riscv64" "0.16.17" - "@esbuild/linux-s390x" "0.16.17" - "@esbuild/linux-x64" "0.16.17" - "@esbuild/netbsd-x64" "0.16.17" - "@esbuild/openbsd-x64" "0.16.17" - "@esbuild/sunos-x64" "0.16.17" - "@esbuild/win32-arm64" "0.16.17" - "@esbuild/win32-ia32" "0.16.17" - "@esbuild/win32-x64" "0.16.17" - escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -11446,191 +7594,36 @@ escape-html@~1.0.3: resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== -escape-latex@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/escape-latex/-/escape-latex-1.2.0.tgz#07c03818cf7dac250cce517f4fda1b001ef2bca1" - integrity sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw== - -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - escape-string-regexp@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + escape-string-regexp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== -escodegen@1.8.x: - version "1.8.1" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" - integrity sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A== - dependencies: - esprima "^2.7.1" - estraverse "^1.9.1" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.2.0" - -eslint-scope@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" - integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== - dependencies: - esrecurse "^4.1.0" - estraverse "^4.1.1" - -eslint-utils@^1.3.1: - version "1.4.3" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" - integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== - dependencies: - eslint-visitor-keys "^1.1.0" - -eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" - integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== - -eslint@^5.16.0, eslint@^5.5.0, eslint@^5.6.0: - version "5.16.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" - integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== - dependencies: - "@babel/code-frame" "^7.0.0" - ajv "^6.9.1" - chalk "^2.1.0" - cross-spawn "^6.0.5" - debug "^4.0.1" - doctrine "^3.0.0" - eslint-scope "^4.0.3" - eslint-utils "^1.3.1" - eslint-visitor-keys "^1.0.0" - espree "^5.0.1" - esquery "^1.0.1" - esutils "^2.0.2" - file-entry-cache "^5.0.1" - functional-red-black-tree "^1.0.1" - glob "^7.1.2" - globals "^11.7.0" - ignore "^4.0.6" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - inquirer "^6.2.2" - js-yaml "^3.13.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.11" - minimatch "^3.0.4" - mkdirp "^0.5.1" - natural-compare "^1.4.0" - optionator "^0.8.2" - path-is-inside "^1.0.2" - progress "^2.0.0" - regexpp "^2.0.1" - semver "^5.5.1" - strip-ansi "^4.0.0" - strip-json-comments "^2.0.1" - table "^5.2.3" - text-table "^0.2.0" - -espree@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" - integrity sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A== - dependencies: - acorn "^6.0.7" - acorn-jsx "^5.0.0" - eslint-visitor-keys "^1.0.0" - -esprima-extract-comments@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/esprima-extract-comments/-/esprima-extract-comments-1.1.0.tgz#0dacab567a5900240de6d344cf18c33617becbc9" - integrity sha512-sBQUnvJwpeE9QnPrxh7dpI/dp67erYG4WXEAreAMoelPRpMR7NWb4YtwRPn9b+H1uLQKl/qS8WYmyaljTpjIsw== - dependencies: - esprima "^4.0.0" - -esprima@2.7.x, esprima@^2.7.1: - version "2.7.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" - integrity sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A== - esprima@^4.0.0, esprima@~4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.0.1: - version "1.5.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" - integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^1.9.1: - version "1.9.3" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" - integrity sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA== - -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.1.0, estraverse@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - esutils@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/esutils/-/esutils-1.1.6.tgz#c01ccaa9ae4b897c6d0c3e210ae52f3c7a844375" integrity sha512-RG1ZkUT7iFJG9LSHr7KDuuMSlujfeTtMNIcInURxKAxhMtwQhI3NrQhz26gZQYlsYZQKzsnwtpKrFKj9K9Qu1A== -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== -eth-block-tracker@^4.4.2: - version "4.4.3" - resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-4.4.3.tgz#766a0a0eb4a52c867a28328e9ae21353812cf626" - integrity sha512-A8tG4Z4iNg4mw5tP1Vung9N9IjgMNqpiMoJ/FouSFwNCGHv2X0mmOYwtQOJzki6XN7r7Tyo01S29p7b224I4jw== - dependencies: - "@babel/plugin-transform-runtime" "^7.5.5" - "@babel/runtime" "^7.5.5" - eth-query "^2.1.0" - json-rpc-random-id "^1.0.1" - pify "^3.0.0" - safe-event-emitter "^1.0.1" - -eth-block-tracker@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-5.0.1.tgz#c5ad39902bd0454223b601ec0874f9fcc9f30eed" - integrity sha512-NVs+JDSux0FdmOrl3A2YDcQFkkYf9/qW9irvPmtC7bhMoPAe6oBlaqqe/m9Ixh5rkKqAox4mEyWGpsFmf/IsNw== - dependencies: - "@metamask/safe-event-emitter" "^2.0.0" - json-rpc-random-id "^1.0.1" - pify "^3.0.0" - eth-ens-namehash@2.0.8, eth-ens-namehash@^2.0.8: version "2.0.8" resolved "https://registry.yarnpkg.com/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz#229ac46eca86d52e0c991e7cb2aef83ff0f68bcf" @@ -11639,75 +7632,6 @@ eth-ens-namehash@2.0.8, eth-ens-namehash@^2.0.8: idna-uts46-hx "^2.3.1" js-sha3 "^0.5.7" -eth-gas-reporter@^0.2.16: - version "0.2.25" - resolved "https://registry.yarnpkg.com/eth-gas-reporter/-/eth-gas-reporter-0.2.25.tgz#546dfa946c1acee93cb1a94c2a1162292d6ff566" - integrity sha512-1fRgyE4xUB8SoqLgN3eDfpDfwEfRxh2Sz1b7wzFbyQA+9TekMmvSjjoRu9SKcSVyK+vLkLIsVbJDsTWjw195OQ== - dependencies: - "@ethersproject/abi" "^5.0.0-beta.146" - "@solidity-parser/parser" "^0.14.0" - cli-table3 "^0.5.0" - colors "1.4.0" - ethereum-cryptography "^1.0.3" - ethers "^4.0.40" - fs-readdir-recursive "^1.1.0" - lodash "^4.17.14" - markdown-table "^1.1.3" - mocha "^7.1.1" - req-cwd "^2.0.0" - request "^2.88.0" - request-promise-native "^1.0.5" - sha1 "^1.1.1" - sync-request "^6.0.0" - -eth-json-rpc-filters@^4.2.1: - version "4.2.2" - resolved "https://registry.yarnpkg.com/eth-json-rpc-filters/-/eth-json-rpc-filters-4.2.2.tgz#eb35e1dfe9357ace8a8908e7daee80b2cd60a10d" - integrity sha512-DGtqpLU7bBg63wPMWg1sCpkKCf57dJ+hj/k3zF26anXMzkmtSBDExL8IhUu7LUd34f0Zsce3PYNO2vV2GaTzaw== - dependencies: - "@metamask/safe-event-emitter" "^2.0.0" - async-mutex "^0.2.6" - eth-json-rpc-middleware "^6.0.0" - eth-query "^2.1.2" - json-rpc-engine "^6.1.0" - pify "^5.0.0" - -eth-json-rpc-infura@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/eth-json-rpc-infura/-/eth-json-rpc-infura-5.1.0.tgz#e6da7dc47402ce64c54e7018170d89433c4e8fb6" - integrity sha512-THzLye3PHUSGn1EXMhg6WTLW9uim7LQZKeKaeYsS9+wOBcamRiCQVGHa6D2/4P0oS0vSaxsBnU/J6qvn0MPdow== - dependencies: - eth-json-rpc-middleware "^6.0.0" - eth-rpc-errors "^3.0.0" - json-rpc-engine "^5.3.0" - node-fetch "^2.6.0" - -eth-json-rpc-middleware@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-6.0.0.tgz#4fe16928b34231a2537856f08a5ebbc3d0c31175" - integrity sha512-qqBfLU2Uq1Ou15Wox1s+NX05S9OcAEL4JZ04VZox2NS0U+RtCMjSxzXhLFWekdShUPZ+P8ax3zCO2xcPrp6XJQ== - dependencies: - btoa "^1.2.1" - clone "^2.1.1" - eth-query "^2.1.2" - eth-rpc-errors "^3.0.0" - eth-sig-util "^1.4.2" - ethereumjs-util "^5.1.2" - json-rpc-engine "^5.3.0" - json-stable-stringify "^1.0.1" - node-fetch "^2.6.1" - pify "^3.0.0" - safe-event-emitter "^1.0.1" - -eth-lib@0.2.7: - version "0.2.7" - resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.7.tgz#2f93f17b1e23aec3759cd4a3fe20c1286a3fc1ca" - integrity sha512-VqEBQKH92jNsaE8lG9CTq8M/bc12gdAfb5MY8Ro1hVyXkh7rOtY3m5tRHK3Hus5HqIAAwU2ivcUjTLVwsvf/kw== - dependencies: - bn.js "^4.11.6" - elliptic "^6.4.0" - xhr-request-promise "^0.1.2" - eth-lib@0.2.8, eth-lib@^0.2.8: version "0.2.8" resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.8.tgz#b194058bef4b220ad12ea497431d6cb6aa0623c8" @@ -11729,46 +7653,6 @@ eth-lib@^0.1.26: ws "^3.0.0" xhr-request-promise "^0.1.2" -eth-query@^2.1.0, eth-query@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/eth-query/-/eth-query-2.1.2.tgz#d6741d9000106b51510c72db92d6365456a6da5e" - integrity sha512-srES0ZcvwkR/wd5OQBRA1bIJMww1skfGS0s8wlwK3/oNP4+wnds60krvu5R1QbpRQjMmpG5OMIWro5s7gvDPsA== - dependencies: - json-rpc-random-id "^1.0.0" - xtend "^4.0.1" - -eth-rpc-errors@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/eth-rpc-errors/-/eth-rpc-errors-3.0.0.tgz#d7b22653c70dbf9defd4ef490fd08fe70608ca10" - integrity sha512-iPPNHPrLwUlR9xCSYm7HHQjWBasor3+KZfRvwEWxMz3ca0yqnlBeJrnyphkGIXZ4J7AMAaOLmwy4AWhnxOiLxg== - dependencies: - fast-safe-stringify "^2.0.6" - -eth-rpc-errors@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/eth-rpc-errors/-/eth-rpc-errors-4.0.3.tgz#6ddb6190a4bf360afda82790bb7d9d5e724f423a" - integrity sha512-Z3ymjopaoft7JDoxZcEb3pwdGh7yiYMhOwm2doUt6ASXlMavpNlK6Cre0+IMl2VSGyEU9rkiperQhp5iRxn5Pg== - dependencies: - fast-safe-stringify "^2.0.6" - -eth-sig-util@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.4.2.tgz#8d958202c7edbaae839707fba6f09ff327606210" - integrity sha512-iNZ576iTOGcfllftB73cPB5AN+XUQAT/T8xzsILsghXC1o8gJUqe3RHlcDqagu+biFpYQ61KQrZZJza8eRSYqw== - dependencies: - ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" - ethereumjs-util "^5.1.1" - -ethashjs@~0.0.7: - version "0.0.8" - resolved "https://registry.yarnpkg.com/ethashjs/-/ethashjs-0.0.8.tgz#227442f1bdee409a548fb04136e24c874f3aa6f9" - integrity sha512-/MSbf/r2/Ld8o0l15AymjOTlPqpN8Cr4ByUEA9GtR4x0yAh3TdtDzEg29zMjXCNPI7u6E5fOQdj/Cf9Tc7oVNw== - dependencies: - async "^2.1.2" - buffer-xor "^2.0.1" - ethereumjs-util "^7.0.2" - miller-rabin "^4.0.0" - ethereum-bloom-filters@^1.0.6: version "1.0.10" resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz#3ca07f4aed698e75bd134584850260246a5fed8a" @@ -11776,17 +7660,7 @@ ethereum-bloom-filters@^1.0.6: dependencies: js-sha3 "^0.8.0" -ethereum-common@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.2.0.tgz#13bf966131cce1eeade62a1b434249bb4cb120ca" - integrity sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA== - -ethereum-common@^0.0.18: - version "0.0.18" - resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" - integrity sha512-EoltVQTRNg2Uy4o84qpa2aXymXDJhxm7eos/ACOg0DG4baAbMjhbdAEsx9GeE8sC3XCxnYvrrzZDH8D8MtA2iQ== - -ethereum-cryptography@1.2.0, ethereum-cryptography@^1.0.3, ethereum-cryptography@^1.1.2: +ethereum-cryptography@1.2.0, ethereum-cryptography@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz#5ccfa183e85fdaf9f9b299a79430c044268c9b3a" integrity sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw== @@ -11827,107 +7701,7 @@ ethereum-cryptography@^2.0.0, ethereum-cryptography@^2.1.2: "@scure/bip32" "1.3.1" "@scure/bip39" "1.2.1" -ethereum-types@^3.7.1: - version "3.7.1" - resolved "https://registry.yarnpkg.com/ethereum-types/-/ethereum-types-3.7.1.tgz#8fa75e5d9f5da3c85535ea0d4bcd2614b1d650a8" - integrity sha512-EBQwTGnGZQ9oHK7Za3DFEOxiElksRCoZECkk418vHiE2d59lLSejDZ1hzRVphtFjAu5YqONz4/XuAYdMBg+gWA== - dependencies: - "@types/node" "12.12.54" - bignumber.js "~9.0.2" - -ethereumjs-abi@^0.6.8: - version "0.6.8" - resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz#71bc152db099f70e62f108b7cdfca1b362c6fcae" - integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA== - dependencies: - bn.js "^4.11.8" - ethereumjs-util "^6.0.0" - -"ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git": - version "0.6.8" - resolved "git+https://github.com/ethereumjs/ethereumjs-abi.git#ee3994657fa7a427238e6ba92a84d0b529bbcde0" - dependencies: - bn.js "^4.11.8" - ethereumjs-util "^6.0.0" - -ethereumjs-account@^2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz#eeafc62de544cb07b0ee44b10f572c9c49e00a84" - integrity sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA== - dependencies: - ethereumjs-util "^5.0.0" - rlp "^2.0.0" - safe-buffer "^5.1.1" - -ethereumjs-account@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-3.0.0.tgz#728f060c8e0c6e87f1e987f751d3da25422570a9" - integrity sha512-WP6BdscjiiPkQfF9PVfMcwx/rDvfZTjFKY0Uwc09zSQr9JfIVH87dYIJu0gNhBhpmovV4yq295fdllS925fnBA== - dependencies: - ethereumjs-util "^6.0.0" - rlp "^2.2.1" - safe-buffer "^5.1.1" - -ethereumjs-block@^1.2.2: - version "1.7.1" - resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz#78b88e6cc56de29a6b4884ee75379b6860333c3f" - integrity sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg== - dependencies: - async "^2.0.1" - ethereum-common "0.2.0" - ethereumjs-tx "^1.2.2" - ethereumjs-util "^5.0.0" - merkle-patricia-tree "^2.1.2" - -ethereumjs-block@^2.2.2, ethereumjs-block@~2.2.0, ethereumjs-block@~2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz#c7654be7e22df489fda206139ecd63e2e9c04965" - integrity sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg== - dependencies: - async "^2.0.1" - ethereumjs-common "^1.5.0" - ethereumjs-tx "^2.1.1" - ethereumjs-util "^5.0.0" - merkle-patricia-tree "^2.1.2" - -ethereumjs-blockchain@^4.0.3: - version "4.0.4" - resolved "https://registry.yarnpkg.com/ethereumjs-blockchain/-/ethereumjs-blockchain-4.0.4.tgz#30f2228dc35f6dcf94423692a6902604ae34960f" - integrity sha512-zCxaRMUOzzjvX78DTGiKjA+4h2/sF0OYL1QuPux0DHpyq8XiNoF5GYHtb++GUxVlMsMfZV7AVyzbtgcRdIcEPQ== - dependencies: - async "^2.6.1" - ethashjs "~0.0.7" - ethereumjs-block "~2.2.2" - ethereumjs-common "^1.5.0" - ethereumjs-util "^6.1.0" - flow-stoplight "^1.0.0" - level-mem "^3.0.1" - lru-cache "^5.1.1" - rlp "^2.2.2" - semaphore "^1.1.0" - -ethereumjs-common@^1.1.0, ethereumjs-common@^1.3.2, ethereumjs-common@^1.5.0: - version "1.5.2" - resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz#2065dbe9214e850f2e955a80e650cb6999066979" - integrity sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA== - -ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2: - version "1.3.7" - resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz#88323a2d875b10549b8347e09f4862b546f3d89a" - integrity sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA== - dependencies: - ethereum-common "^0.0.18" - ethereumjs-util "^5.0.0" - -ethereumjs-tx@^2.1.1, ethereumjs-tx@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz#5dfe7688bf177b45c9a23f86cf9104d47ea35fed" - integrity sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw== - dependencies: - ethereumjs-common "^1.5.0" - ethereumjs-util "^6.0.0" - -ethereumjs-util@7.1.5, ethereumjs-util@^7.0.10, ethereumjs-util@^7.0.2, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.1, ethereumjs-util@^7.1.2, ethereumjs-util@^7.1.5: +ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.1, ethereumjs-util@^7.1.2, ethereumjs-util@^7.1.5: version "7.1.5" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== @@ -11938,85 +7712,6 @@ ethereumjs-util@7.1.5, ethereumjs-util@^7.0.10, ethereumjs-util@^7.0.2, ethereum ethereum-cryptography "^0.1.3" rlp "^2.2.4" -ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.2, ethereumjs-util@^5.1.5: - version "5.2.1" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz#a833f0e5fca7e5b361384dc76301a721f537bf65" - integrity sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ== - dependencies: - bn.js "^4.11.0" - create-hash "^1.1.2" - elliptic "^6.5.2" - ethereum-cryptography "^0.1.3" - ethjs-util "^0.1.3" - rlp "^2.0.0" - safe-buffer "^5.1.1" - -ethereumjs-util@^6.0.0, ethereumjs-util@^6.1.0, ethereumjs-util@^6.2.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69" - integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw== - dependencies: - "@types/bn.js" "^4.11.3" - bn.js "^4.11.0" - create-hash "^1.1.2" - elliptic "^6.5.2" - ethereum-cryptography "^0.1.3" - ethjs-util "0.1.6" - rlp "^2.2.3" - -ethereumjs-vm@4.1.3: - version "4.1.3" - resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-4.1.3.tgz#dc8eb45f47d775da9f0b2437d5e20896fdf66f37" - integrity sha512-RTrD0y7My4O6Qr1P2ZIsMfD6RzL6kU/RhBZ0a5XrPzAeR61crBS7or66ohDrvxDI/rDBxMi+6SnsELih6fzalw== - dependencies: - async "^2.1.2" - async-eventemitter "^0.2.2" - core-js-pure "^3.0.1" - ethereumjs-account "^3.0.0" - ethereumjs-block "^2.2.2" - ethereumjs-blockchain "^4.0.3" - ethereumjs-common "^1.5.0" - ethereumjs-tx "^2.1.2" - ethereumjs-util "^6.2.0" - fake-merkle-patricia-tree "^1.0.1" - functional-red-black-tree "^1.0.1" - merkle-patricia-tree "^2.3.2" - rustbn.js "~0.2.0" - safe-buffer "^5.1.1" - util.promisify "^1.0.0" - -ethereumjs-vm@^2.0.2, ethereumjs-vm@^2.3.4: - version "2.6.0" - resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz#76243ed8de031b408793ac33907fb3407fe400c6" - integrity sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw== - dependencies: - async "^2.1.2" - async-eventemitter "^0.2.2" - ethereumjs-account "^2.0.3" - ethereumjs-block "~2.2.0" - ethereumjs-common "^1.1.0" - ethereumjs-util "^6.0.0" - fake-merkle-patricia-tree "^1.0.1" - functional-red-black-tree "^1.0.1" - merkle-patricia-tree "^2.3.2" - rustbn.js "~0.2.0" - safe-buffer "^5.1.1" - -ethereumjs-wallet@^0.6.0, ethereumjs-wallet@^0.6.3: - version "0.6.5" - resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.5.tgz#685e9091645cee230ad125c007658833991ed474" - integrity sha512-MDwjwB9VQVnpp/Dc1XzA6J1a3wgHQ4hSvA1uWNatdpOrtCbPVuQSKSyRnjLvS0a+KKMw2pvQ9Ybqpb3+eW8oNA== - dependencies: - aes-js "^3.1.1" - bs58check "^2.1.2" - ethereum-cryptography "^0.1.3" - ethereumjs-util "^6.0.0" - randombytes "^2.0.6" - safe-buffer "^5.1.2" - scryptsy "^1.2.1" - utf8 "^3.0.0" - uuid "^3.3.2" - ethereumjs-wallet@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-1.0.2.tgz#2c000504b4c71e8f3782dabe1113d192522e99b6" @@ -12031,23 +7726,7 @@ ethereumjs-wallet@^1.0.1: utf8 "^3.0.0" uuid "^8.3.2" -ethers@4.0.0-beta.3: - version "4.0.0-beta.3" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.0-beta.3.tgz#15bef14e57e94ecbeb7f9b39dd0a4bd435bc9066" - integrity sha512-YYPogooSknTwvHg3+Mv71gM/3Wcrx+ZpCzarBj3mqs9njjRkrOo2/eufzhHloOCo3JSoNI4TQJJ6yU5ABm3Uog== - dependencies: - "@types/node" "^10.3.2" - aes-js "3.0.0" - bn.js "^4.4.0" - elliptic "6.3.3" - hash.js "1.1.3" - js-sha3 "0.5.7" - scrypt-js "2.0.3" - setimmediate "1.0.4" - uuid "2.0.1" - xmlhttprequest "1.8.0" - -ethers@^4.0.20, ethers@^4.0.32, ethers@^4.0.40, ethers@~4.0.4: +ethers@^4.0.32: version "4.0.49" resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.49.tgz#0eb0e9161a0c8b4761be547396bbe2fb121a8894" integrity sha512-kPltTvWiyu+OktYy1IStSO16i2e7cS9D9OxZ81q2UUaiNPVrm/RTcbxamCXF9VUSKzJIdJV68EAIhTEVBalRWg== @@ -12062,7 +7741,7 @@ ethers@^4.0.20, ethers@^4.0.32, ethers@^4.0.40, ethers@~4.0.4: uuid "2.0.1" xmlhttprequest "1.8.0" -ethers@^5.0.13, ethers@^5.2.0, ethers@^5.7.1: +ethers@^5.0.13: version "5.7.2" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== @@ -12098,7 +7777,7 @@ ethers@^5.0.13, ethers@^5.2.0, ethers@^5.7.1: "@ethersproject/web" "5.7.1" "@ethersproject/wordlists" "5.7.0" -ethjs-unit@0.1.6, ethjs-unit@^0.1.6: +ethjs-unit@0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" integrity sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw== @@ -12106,29 +7785,11 @@ ethjs-unit@0.1.6, ethjs-unit@^0.1.6: bn.js "4.11.6" number-to-bn "1.7.0" -ethjs-util@0.1.6, ethjs-util@^0.1.3: - version "0.1.6" - resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" - integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== - dependencies: - is-hex-prefixed "1.0.0" - strip-hex-prefix "1.0.0" - event-target-shim@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== -eventemitter3@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.0.tgz#090b4d6cdbd645ed10bf750d4b5407942d7ba163" - integrity sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA== - -eventemitter3@3.1.2, eventemitter3@^3.1.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7" - integrity sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q== - eventemitter3@4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" @@ -12149,7 +7810,7 @@ events@^3.0.0, events@^3.1.0, events@^3.3.0: resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== -evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: +evp_bytestokey@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== @@ -12205,7 +7866,7 @@ execa@^2.1.0: signal-exit "^3.0.2" strip-final-newline "^2.0.0" -execa@^5.0.0, execa@^5.1.1: +execa@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== @@ -12220,33 +7881,11 @@ execa@^5.0.0, execa@^5.1.1: signal-exit "^3.0.3" strip-final-newline "^2.0.0" -execa@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-6.1.0.tgz#cea16dee211ff011246556388effa0818394fb20" - integrity sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA== - dependencies: - cross-spawn "^7.0.3" - get-stream "^6.0.1" - human-signals "^3.0.1" - is-stream "^3.0.0" - merge-stream "^2.0.0" - npm-run-path "^5.1.0" - onetime "^6.0.0" - signal-exit "^3.0.7" - strip-final-newline "^3.0.0" - exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== -expand-brackets@^0.1.1, expand-brackets@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" - integrity sha512-hxx03P2dJxss6ceIeri9cmYOT4SRs3Zk3afZwWpOsRqLqprhTR8u++SlC+sFGsQr7WGFPdMF7Gjc1njDLDK6UA== - dependencies: - is-posix-bracket "^0.1.0" - expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" @@ -12260,32 +7899,11 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expand-range@^1.8.1: - version "1.8.2" - resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - integrity sha512-AFASGfIlnIbkKPQwX1yHaDjFvh/1gyKJODme52V6IORh69uEYgZp0o9C+qsIGNVEiuuhQU0CSSl++Rlegg1qvA== - dependencies: - fill-range "^2.1.0" - expand-template@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== -expand-tilde@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-1.2.2.tgz#0b81eba897e5a3d31d1c3d102f8f01441e559449" - integrity sha512-rtmc+cjLZqnu9dSYosX9EWmSJhTwpACgJQTfj4hgg2JjOD/6SIQalZrt4a3aQeh++oNxkazcaxrhPUj6+g5G/Q== - dependencies: - os-homedir "^1.0.1" - -expand-tilde@^2.0.0, expand-tilde@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" - integrity sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw== - dependencies: - homedir-polyfill "^1.0.1" - expect@^29.0.0, expect@^29.5.0: version "29.5.0" resolved "https://registry.yarnpkg.com/expect/-/expect-29.5.0.tgz#68c0509156cb2a0adb8865d413b137eeaae682f7" @@ -12297,14 +7915,7 @@ expect@^29.0.0, expect@^29.5.0: jest-message-util "^29.5.0" jest-util "^29.5.0" -export-files@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/export-files/-/export-files-2.1.1.tgz#bbf64574053a09e4eb98e5f43501d572b2c3ce7f" - integrity sha512-r2x1Zt0OKgdXRy0bXis3sOI8TNYmo5Fe71qXwsvpYaMvIlH5G0fWEf3AYiE2bONjePdSOojca7Jw+p9CQ6/6NQ== - dependencies: - lazy-cache "^1.0.3" - -express@^4.14.0, express@^4.17.1, express@^4.17.6: +express@^4.14.0, express@^4.17.6: version "4.18.2" resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== @@ -12348,7 +7959,7 @@ ext@^1.1.2: dependencies: type "^2.7.2" -extend-shallow@^2.0.0, extend-shallow@^2.0.1: +extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== @@ -12363,7 +7974,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: assign-symbols "^1.0.0" is-extendable "^1.0.1" -extend@^3.0.0, extend@^3.0.1, extend@^3.0.2, extend@~3.0.2: +extend@^3.0.2, extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== @@ -12382,13 +7993,6 @@ external-editor@^3.0.3, external-editor@^3.1.0: iconv-lite "^0.4.24" tmp "^0.0.33" -extglob@^0.3.0, extglob@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" - integrity sha512-1FOj1LOwn42TMrruOHGt18HemVnbwAmAak7krWk+wa93KXxGbK+2jpezm+ytJYDaBX0/SPLZFHKM7m+tKobWGg== - dependencies: - is-extglob "^1.0.0" - extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" @@ -12403,14 +8007,6 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" -extract-comments@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/extract-comments/-/extract-comments-1.1.0.tgz#b90bca033a056bd69b8ba1c6b6b120fc2ee95c18" - integrity sha512-dzbZV2AdSSVW/4E7Ti5hZdHWbA+Z80RJsJhr5uiL10oyjl/gy7/o+HI1HwK4/WSZhlq4SNKU3oUzXlM13Qx02Q== - dependencies: - esprima-extract-comments "^1.1.0" - parse-code-context "^1.0.0" - extract-stack@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/extract-stack/-/extract-stack-1.0.0.tgz#b97acaf9441eea2332529624b732fc5a1c8165fa" @@ -12436,13 +8032,6 @@ eyes@0.1.x: resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" integrity sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ== -fake-merkle-patricia-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz#4b8c3acfb520afadf9860b1f14cd8ce3402cddd3" - integrity sha512-Tgq37lkc9pUIgIKw5uitNUKcgcYL3R6JvXtKQbOf/ZSavXbidsksgp/pAY6p//uhw0I4yoMsvTSovvVIsk/qxA== - dependencies: - checkpoint-store "^1.1.0" - fast-check@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/fast-check/-/fast-check-3.1.1.tgz#72c5ae7022a4e86504762e773adfb8a5b0b01252" @@ -12455,11 +8044,6 @@ fast-deep-equal@^3.1.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-diff@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" - integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== - fast-glob@3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1" @@ -12494,17 +8078,6 @@ fast-glob@^3.0.3, fast-glob@^3.2.9: merge2 "^1.3.0" micromatch "^4.0.4" -fast-glob@^3.3.0: - version "3.3.2" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" - integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" @@ -12517,16 +8090,6 @@ fast-levenshtein@^3.0.0: dependencies: fastest-levenshtein "^1.0.7" -fast-levenshtein@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== - -fast-safe-stringify@^2.0.6: - version "2.1.1" - resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" - integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== - fast-text-encoding@^1.0.0, fast-text-encoding@^1.0.3: version "1.0.6" resolved "https://registry.yarnpkg.com/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz#0aa25f7f638222e3396d72bf936afcf1d42d6867" @@ -12558,13 +8121,6 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" -fd-slicer@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" - integrity sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g== - dependencies: - pend "~1.2.0" - fetch-blob@^3.1.2, fetch-blob@^3.1.4: version "3.2.0" resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9" @@ -12573,13 +8129,6 @@ fetch-blob@^3.1.2, fetch-blob@^3.1.4: node-domexception "^1.0.0" web-streams-polyfill "^3.0.3" -fetch-cookie@0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/fetch-cookie/-/fetch-cookie-0.11.0.tgz#e046d2abadd0ded5804ce7e2cae06d4331c15407" - integrity sha512-BQm7iZLFhMWFy5CZ/162sAGjBfdNWb7a8LEqqnzsHFhxT/X/SVj/z2t2nu3aJvjlbQkrAlTUApplPRjWyH4mhA== - dependencies: - tough-cookie "^2.3.3 || ^3.0.1 || ^4.0.0" - fetch-mock@9.10.4: version "9.10.4" resolved "https://registry.yarnpkg.com/fetch-mock/-/fetch-mock-9.10.4.tgz#e5f98c7d56d57b29caec55d928930150f39519ba" @@ -12613,40 +8162,11 @@ fetch-mock@^9.11.0: figures@3.2.0, figures@^3.0.0: version "3.2.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" - integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== - dependencies: - escape-string-regexp "^1.0.5" - -figures@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" - integrity sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA== + resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" + integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== dependencies: escape-string-regexp "^1.0.5" -file-entry-cache@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" - integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== - dependencies: - flat-cache "^2.0.1" - -file-type@^3.8.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" - integrity sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA== - -file-type@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" - integrity sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ== - -file-type@^6.1.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" - integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg== - file-uri-to-path@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" @@ -12659,30 +8179,6 @@ filelist@^1.0.1: dependencies: minimatch "^5.0.1" -filename-regex@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" - integrity sha512-BTCqyBaWBTsauvnHiE8i562+EdJj+oUpkqWp2R1iCoR8f6oo8STRu3of7WJJ0TqWtxN50a5YFpzYK4Jj9esYfQ== - -fill-keys@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/fill-keys/-/fill-keys-1.0.2.tgz#9a8fa36f4e8ad634e3bf6b4f3c8882551452eb20" - integrity sha512-tcgI872xXjwFF4xgQmLxi76GnwJG3g/3isB1l4/G5Z4zrbddGpBjqZCO9oEAcB5wX0Hj/5iQB3toxfO7in1hHA== - dependencies: - is-object "~1.0.1" - merge-descriptors "~1.0.0" - -fill-range@^2.1.0: - version "2.2.4" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" - integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q== - dependencies: - is-number "^2.1.0" - isobject "^2.0.0" - randomatic "^3.0.0" - repeat-element "^1.1.2" - repeat-string "^1.5.2" - fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" @@ -12713,31 +8209,29 @@ finalhandler@1.2.0: statuses "2.0.1" unpipe "~1.0.0" -find-cache-dir@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" - integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + integrity sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA== dependencies: - commondir "^1.0.1" - make-dir "^2.0.0" - pkg-dir "^3.0.0" + path-exists "^2.0.0" + pinkie-promise "^2.0.0" -find-replace@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-1.0.3.tgz#b88e7364d2d9c959559f388c66670d6130441fa0" - integrity sha512-KrUnjzDCD9426YnCP56zGYy/eieTnhtK6Vn++j+JJzmlsWWwEkDnsyVF575spT6HJ6Ow9tlbT3TQTDsa+O4UWA== +find-up@^2.0.0, find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== dependencies: - array-back "^1.0.4" - test-value "^2.1.0" + locate-path "^2.0.0" -find-up@3.0.0, find-up@^3.0.0: +find-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== dependencies: locate-path "^3.0.0" -find-up@4.1.0, find-up@^4.0.0, find-up@^4.1.0: +find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== @@ -12745,7 +8239,7 @@ find-up@4.1.0, find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" -find-up@5.0.0, find-up@^5.0.0: +find-up@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== @@ -12753,29 +8247,6 @@ find-up@5.0.0, find-up@^5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" -find-up@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - integrity sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA== - dependencies: - path-exists "^2.0.0" - pinkie-promise "^2.0.0" - -find-up@^2.0.0, find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== - dependencies: - locate-path "^2.0.0" - -find-up@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-6.3.0.tgz#2abab3d3280b2dc7ac10199ef324c4e002c8c790" - integrity sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw== - dependencies: - locate-path "^7.1.0" - path-exists "^5.0.0" - find-yarn-workspace-root2@1.2.16: version "1.2.16" resolved "https://registry.yarnpkg.com/find-yarn-workspace-root2/-/find-yarn-workspace-root2-1.2.16.tgz#60287009dd2f324f59646bdb4b7610a6b301c2a9" @@ -12791,101 +8262,28 @@ find-yarn-workspace-root@^2.0.0: dependencies: micromatch "^4.0.2" -findup-sync@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-1.0.0.tgz#6f7e4b57b6ee3a4037b4414eaedea3f58f71e0ec" - integrity sha512-VyWlYDW822Fybow9EjxaArNhS296zu4eYUWI+l2SVfo0/iqvodwI83RBwXSMczgcEejZGOg5+cGJc53OIdtjjA== - dependencies: - detect-file "^0.1.0" - is-glob "^2.0.1" - micromatch "^2.3.7" - resolve-dir "^0.1.0" - -flat-cache@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" - integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== - dependencies: - flatted "^2.0.0" - rimraf "2.6.3" - write "1.0.3" - -flat@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.1.tgz#a392059cc382881ff98642f5da4dde0a959f309b" - integrity sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA== - dependencies: - is-buffer "~2.0.3" - flat@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== -flatted@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" - integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== - -flow-stoplight@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/flow-stoplight/-/flow-stoplight-1.0.0.tgz#4a292c5bcff8b39fa6cc0cb1a853d86f27eeff7b" - integrity sha512-rDjbZUKpN8OYhB0IE/vY/I8UWO/602IIJEU/76Tv4LvYnwHCk0BCsvz4eRr9n+FQcri7L5cyaXOo0+/Kh4HisA== - -follow-redirects@1.5.10: - version "1.5.10" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a" - integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ== - dependencies: - debug "=3.1.0" - -follow-redirects@^1.12.1, follow-redirects@^1.14.0, follow-redirects@^1.14.7, follow-redirects@^1.15.0: +follow-redirects@^1.14.0, follow-redirects@^1.15.0: version "1.15.2" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== -follow-redirects@^1.14.8: - version "1.15.3" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.3.tgz#fe2f3ef2690afce7e82ed0b44db08165b207123a" - integrity sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q== - -for-each@^0.3.3, for-each@~0.3.3: +for-each@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== dependencies: is-callable "^1.1.3" -for-in@^0.1.3: - version "0.1.8" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-0.1.8.tgz#d8773908e31256109952b1fdb9b3fa867d2775e1" - integrity sha512-F0to7vbBSHP8E3l6dCjxNOLuSFAACIxFy3UehTUlG7svlXi37HHsDkyVcHo0Pq8QwrE+pXvWSVX3ZT1T9wAZ9g== - -for-in@^1.0.1, for-in@^1.0.2: +for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" integrity sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ== -for-own@^0.1.3, for-own@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" - integrity sha512-SKmowqGTJoPzLO1T0BBJpkfp3EMacCMOuH40hOUbrbzElVktk4DioXVM99QkLCyKoiuOmyjgcWMpVz2xjE7LZw== - dependencies: - for-in "^1.0.1" - -foreach@^2.0.4: - version "2.0.6" - resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.6.tgz#87bcc8a1a0e74000ff2bf9802110708cfb02eb6e" - integrity sha512-k6GAGDyqLe9JaebCsFCoudPPWfihKu8pylYXRlqP1J7ms39iPoTtk2fviNglIeQEwdh0bQeKJ01ZPyuyQvKzwg== - -foreground-child@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" - integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== - dependencies: - cross-spawn "^7.0.0" - signal-exit "^4.0.1" - forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -12896,24 +8294,6 @@ form-data-encoder@1.7.1: resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-1.7.1.tgz#ac80660e4f87ee0d3d3c3638b7da8278ddb8ec96" integrity sha512-EFRDrsMm/kyqbTQocNvRXMLjc7Es2Vk+IQFx/YW7hkUH1eBl4J1fqiP34l74Yt0pFLCNpc06fkbVk00008mzjg== -form-data@^2.2.0, form-data@^2.5.0: - version "2.5.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" - integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - -form-data@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" - integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - form-data@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" @@ -12949,11 +8329,6 @@ fp-ts@2.1.1: resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-2.1.1.tgz#c910544499d7c959351bb4260ee7c44a544084c1" integrity sha512-YcWhMdDCFCja0MmaDroTgNu+NWWrrnUEn92nvDgrtVy9Z71YFnhNVIghoHPt8gs82ijoMzFGeWKvArbyICiJgw== -fraction.js@4.0.12: - version "4.0.12" - resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.0.12.tgz#0526d47c65a5fb4854df78bc77f7bec708d7b8c3" - integrity sha512-8Z1K0VTG4hzYY7kA/1sj4/r1/RWLBD3xwReT/RCrUCbzPszjNQCCsy3ktkU/eaEqX3MYa4pY37a52eiBlPMlhA== - fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" @@ -12971,11 +8346,6 @@ fs-constants@^1.0.0: resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== -fs-exists-sync@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add" - integrity sha512-cR/vflFyPZtrN6b38ZyWxpWdhlXrzZEBawlpBQMq7033xVY7/kg0GDMBK5jg8lDYQckdJ5x/YC88lM3C7VMsLg== - fs-extra@^0.30.0: version "0.30.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" @@ -12987,15 +8357,6 @@ fs-extra@^0.30.0: path-is-absolute "^1.0.0" rimraf "^2.2.8" -fs-extra@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" - integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - fs-extra@^11.1.0: version "11.1.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.1.1.tgz#da69f7c39f3b002378b0954bb6ae7efdc0876e2d" @@ -13014,15 +8375,6 @@ fs-extra@^4.0.2: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" - integrity sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - fs-extra@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-6.0.1.tgz#8abc128f7946e310135ddc93b98bddb410e7a34b" @@ -13050,7 +8402,7 @@ fs-extra@^8.1, fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^9.0, fs-extra@^9.0.0, fs-extra@^9.0.1, fs-extra@^9.1.0: +fs-extra@^9.0, fs-extra@^9.0.1, fs-extra@^9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== @@ -13074,26 +8426,16 @@ fs-minipass@^2.0.0, fs-minipass@^2.1.0: dependencies: minipass "^3.0.0" -fs-readdir-recursive@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" - integrity sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA== - fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fsevents@^2.3.2, fsevents@~2.3.2: +fsevents@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== -fsevents@~2.1.1, fsevents@~2.1.2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" - integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== - function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" @@ -13104,16 +8446,6 @@ function-bind@^1.1.2: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== -function.prototype.name@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" - integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.0" - functions-have-names "^1.2.2" - function.prototype.name@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" @@ -13124,17 +8456,12 @@ function.prototype.name@^1.1.6: es-abstract "^1.22.1" functions-have-names "^1.2.3" -functional-red-black-tree@^1.0.1, functional-red-black-tree@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== - -functions-have-names@^1.2.2, functions-have-names@^1.2.3: +functions-have-names@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== -ganache@7.8.0, ganache@^7.4.0, "ganache@npm:@celo/ganache@7.8.0-unofficial.0", "ganache@npm:@soloseng/ganache@7.8.0-beta.1": +"ganache@npm:@celo/ganache@7.8.0-unofficial.0", "ganache@npm:@soloseng/ganache@7.8.0-beta.1": version "7.8.0-beta.1" resolved "https://registry.yarnpkg.com/@soloseng/ganache/-/ganache-7.8.0-beta.1.tgz#168d3c2f1ea05c350e972f227872d4a4b15e5f9e" integrity sha512-ptjs631aKpxG7xexDDyxh5NevKQaUcSfm3/Aeh0smJ/3xQgNrJ+st6CVYVbVbhGkgNcq9NIvCCaIgt0L64GOCA== @@ -13169,30 +8496,6 @@ gauge@^4.0.3: strip-ansi "^6.0.1" wide-align "^1.1.5" -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg== - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - -gaxios@^1.0.2, gaxios@^1.0.4, gaxios@^1.2.1, gaxios@^1.2.2, gaxios@^1.5.0: - version "1.8.4" - resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-1.8.4.tgz#e08c34fe93c0a9b67a52b7b9e7a64e6435f9a339" - integrity sha512-BoENMnu1Gav18HcpV9IleMPZ9exM+AvUjrAOV4Mzs/vfz2Lu/ABv451iEXByKiMPn2M140uul1txXCg83sAENw== - dependencies: - abort-controller "^3.0.0" - extend "^3.0.2" - https-proxy-agent "^2.2.1" - node-fetch "^2.3.0" - gaxios@^4.0.0: version "4.3.3" resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-4.3.3.tgz#d44bdefe52d34b6435cc41214fdb160b64abfc22" @@ -13214,14 +8517,6 @@ gaxios@^5.0.0: is-stream "^2.0.0" node-fetch "^2.6.9" -gcp-metadata@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-1.0.0.tgz#5212440229fa099fc2f7c2a5cdcb95575e9b2ca6" - integrity sha512-Q6HrgfrCQeEircnNP3rCcEgiDv7eF9+1B+1MMgpE190+/+0mjQR8PxeOaRgxZWmdDAF9EIryHB9g1moPiw1SbQ== - dependencies: - gaxios "^1.0.2" - json-bigint "^0.3.0" - gcp-metadata@^4.2.0: version "4.3.1" resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-4.3.1.tgz#fb205fe6a90fef2fd9c85e6ba06e5559ee1eefa9" @@ -13238,23 +8533,6 @@ gcp-metadata@^5.0.0: gaxios "^5.0.0" json-bigint "^1.0.0" -gcs-resumable-upload@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/gcs-resumable-upload/-/gcs-resumable-upload-1.1.0.tgz#2b06f5876dcf60f18a309343f79ed951aff01399" - integrity sha512-uBz7uHqp44xjSDzG3kLbOYZDjxxR/UAGbB47A0cC907W6yd2LkcyFDTHg+bjivkHMwiJlKv4guVWcjPCk2zScg== - dependencies: - abort-controller "^2.0.2" - configstore "^4.0.0" - gaxios "^1.5.0" - google-auth-library "^3.0.0" - pumpify "^1.5.1" - stream-events "^1.0.4" - -generate-password@^1.5.1: - version "1.7.0" - resolved "https://registry.yarnpkg.com/generate-password/-/generate-password-1.7.0.tgz#00ba4eb1e71f89a72307b0d6604ee0d4e7f5770c" - integrity sha512-WPCtlfy0jexf7W5IbwxGUgpIDvsZIohbI2DAq2Q6TSlKKis+G4GT9sxvPxrZUGL8kP6WUXMWNqYnxY6DDKAdFA== - gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" @@ -13270,25 +8548,6 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-func-name@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" - integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== - -get-installed-path@^2.0.3: - version "2.1.1" - resolved "https://registry.yarnpkg.com/get-installed-path/-/get-installed-path-2.1.1.tgz#a1f33dc6b8af542c9331084e8edbe37fe2634152" - integrity sha512-Qkn9eq6tW5/q9BDVdMpB8tOHljX9OSP0jRC5TRNVA4qRc839t4g8KQaR8t0Uv0EFVL0MlyG7m/ofjEgAROtYsA== - dependencies: - global-modules "1.0.0" - -get-installed-path@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/get-installed-path/-/get-installed-path-4.0.8.tgz#a4fee849f5f327c12c551bb37477acd5151e5f7d" - integrity sha512-PmANK1xElIHlHH2tXfOoTnSDUjX1X3GvKK6ZyLbUnSCCn1pADwu67eVWttuPzJWrXDDT2MfO6uAaKILOFfitmA== - dependencies: - global-modules "1.0.0" - get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f" @@ -13323,37 +8582,17 @@ get-pkg-repo@^4.0.0: through2 "^2.0.0" yargs "^16.2.0" -get-port@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" - integrity sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg== - get-port@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/get-port/-/get-port-5.1.1.tgz#0469ed07563479de6efb986baf053dcd7d4e3193" integrity sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ== -get-proxy@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/get-proxy/-/get-proxy-1.1.0.tgz#894854491bc591b0f147d7ae570f5c678b7256eb" - integrity sha512-3cJ+77wC52qD2PqWNXtB2HkU6tQXc/X3hSMtSN0Y8c8nbYMMxF7vpsjH4H0iSt+28l/NK13DKl8iKAVGkqDFnA== - dependencies: - rc "^1.1.2" - -get-stream@^2.2.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" - integrity sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA== - dependencies: - object-assign "^4.0.1" - pinkie-promise "^2.0.0" - get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" integrity sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ== -get-stream@^4.0.0, get-stream@^4.1.0: +get-stream@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== @@ -13380,16 +8619,6 @@ get-symbol-description@^1.0.0: call-bind "^1.0.2" get-intrinsic "^1.1.1" -get-value@^1.1.5: - version "1.3.1" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-1.3.1.tgz#8ac7ef4f20382392b2646548f9b9ad2dc6c89642" - integrity sha512-TrDxHI5wqgpM5Guhoz7xmblwy7kzhDauSs4df3NP907yFmLtCkOau8YtGo087jZXKDwP22NG6fCo0UA4EFLjOw== - dependencies: - arr-flatten "^1.0.1" - is-extendable "^0.1.1" - lazy-cache "^0.2.4" - noncharacters "^1.1.0" - get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -13461,74 +8690,6 @@ github-slugger@^1.2.1: resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.5.0.tgz#17891bbc73232051474d68bd867a34625c955f7d" integrity sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw== -glob-base@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" - integrity sha512-ab1S1g1EbO7YzauaJLkgLp7DZVAqj9M/dvKlTt8DkXA2tiOIcSMrlVI2J1RZyB5iJVccEscjGn+kpOG9788MHA== - dependencies: - glob-parent "^2.0.0" - is-glob "^2.0.0" - -glob-fs-dotfiles@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/glob-fs-dotfiles/-/glob-fs-dotfiles-0.1.6.tgz#b4f17b73c188418aba47cd206cf5a7226b4a8949" - integrity sha512-CUTouLo3beDkPJG3Pt/3Qieq1tfGEKVSb/kM7j3m93sdM6LUx/NRlnpy7SGA2Q8/NPXoUUd4F7CNqngX0PdYPg== - -glob-fs-gitignore@^0.1.5: - version "0.1.6" - resolved "https://registry.yarnpkg.com/glob-fs-gitignore/-/glob-fs-gitignore-0.1.6.tgz#885e6f412f859cc59756154829dbd55726cde992" - integrity sha512-0NSbtFTLX0mS2QTgAqATtLiEAYI8xsyLmkQ3Pm+RoOTxhOqVMfzOYI5kzaqt8oECoUmmw7xk+Gp2pjjhRfFq7w== - dependencies: - findup-sync "^1.0.0" - micromatch "^2.3.11" - parse-gitignore "^0.2.0" - -glob-fs@^0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/glob-fs/-/glob-fs-0.1.7.tgz#9a7ebbfc694fae9cebec5d59dace93ecfb364f26" - integrity sha512-f0U3u9xK8MEYtKDCnZXvZrZAy4uNp+KSA4xfaKI/NxbE6HXhqUBQ485Uwd6jQa/Q6z1yKi804WT9y53RrwuMxQ== - dependencies: - async "^1.3.0" - bluebird "^2.9.33" - component-emitter "^1.2.0" - ends-with "^0.2.0" - export-files "^2.0.1" - extend-shallow "^2.0.0" - get-value "^1.1.5" - glob-fs-dotfiles "^0.1.6" - glob-fs-gitignore "^0.1.5" - glob-parent "^1.2.0" - graceful-fs "^4.1.2" - is-dotdir "^0.1.0" - is-dotfile "^1.0.1" - is-glob "^2.0.0" - is-windows "^0.1.0" - kind-of "^2.0.0" - lazy-cache "^0.1.0" - micromatch jonschlinkert/micromatch#2.2.0 - mixin-object "^2.0.0" - object-visit "^0.1.0" - object.omit "^1.1.0" - parse-filepath "^0.6.1" - relative "^3.0.1" - set-value "^0.2.0" - starts-with "^1.0.2" - through2 "^2.0.0" - -glob-parent@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-1.3.0.tgz#971edd816ed5db58705b58079647a64d0aef7968" - integrity sha512-hTmuuCjsIMiB85432X8VgmlgWVn99Np49NOWsRyfPkvsFBmsHOoCkOoFGNrMgauLMDD06Mzw+uVTw+oWNCAzgQ== - dependencies: - is-glob "^2.0.0" - -glob-parent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - integrity sha512-JDYOvfxio/t42HKdxkAYaCiBN7oYiuxykOxKxdaUW5Qn0zaYN3gRQWolrwdnf0shM9/EP0ebuuTmyoXNr1cC5w== - dependencies: - is-glob "^2.0.0" - glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" @@ -13537,7 +8698,7 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob-parent@^5.1.1, glob-parent@^5.1.2, glob-parent@~5.1.0, glob-parent@~5.1.2: +glob-parent@^5.1.1, glob-parent@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== @@ -13554,30 +8715,6 @@ glob-to-regexp@^0.4.0: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== -glob@7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@7.1.3: - version "7.1.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" - integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - glob@7.1.4: version "7.1.4" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" @@ -13590,52 +8727,6 @@ glob@7.1.4: once "^1.3.0" path-is-absolute "^1.0.0" -glob@7.1.6: - version "7.1.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" - integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^10.3.7: - version "10.3.10" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b" - integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g== - dependencies: - foreground-child "^3.1.0" - jackspeak "^2.3.5" - minimatch "^9.0.1" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - path-scurry "^1.10.1" - -glob@^5.0.15: - version "5.0.15" - resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" - integrity sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA== - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - glob@^6.0.1: version "6.0.4" resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" @@ -13647,7 +8738,7 @@ glob@^6.0.1: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.0, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@~7.2.3: +glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -13670,44 +8761,6 @@ glob@^8.0.1: minimatch "^5.0.1" once "^1.3.0" -global-modules@1.0.0, global-modules@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" - integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== - dependencies: - global-prefix "^1.0.1" - is-windows "^1.0.1" - resolve-dir "^1.0.0" - -global-modules@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-0.2.3.tgz#ea5a3bed42c6d6ce995a4f8a1269b5dae223828d" - integrity sha512-JeXuCbvYzYXcwE6acL9V2bAOeSIGl4dD+iwLY9iUx2VBJJ80R18HCn+JCwHM9Oegdfya3lEkGCdaRkSyc10hDA== - dependencies: - global-prefix "^0.1.4" - is-windows "^0.2.0" - -global-prefix@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-0.1.5.tgz#8d3bc6b8da3ca8112a160d8d496ff0462bfef78f" - integrity sha512-gOPiyxcD9dJGCEArAhF4Hd0BAqvAe/JzERP7tYumE4yIkmIedPUVXcJFWbV3/p/ovIIvKjkrTk+f1UVkq7vvbw== - dependencies: - homedir-polyfill "^1.0.0" - ini "^1.3.4" - is-windows "^0.2.0" - which "^1.2.12" - -global-prefix@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" - integrity sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg== - dependencies: - expand-tilde "^2.0.2" - homedir-polyfill "^1.0.1" - ini "^1.3.4" - is-windows "^1.0.1" - which "^1.2.14" - global@~4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406" @@ -13716,7 +8769,7 @@ global@~4.4.0: min-document "^2.19.0" process "^0.11.10" -globals@^11.1.0, globals@^11.7.0: +globals@^11.1.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== @@ -13754,17 +8807,6 @@ globby@^11.0.0, globby@^11.0.1, globby@^11.0.2, globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" -globby@^13.1.3: - version "13.2.2" - resolved "https://registry.yarnpkg.com/globby/-/globby-13.2.2.tgz#63b90b1bf68619c2135475cbd4e71e66aa090592" - integrity sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w== - dependencies: - dir-glob "^3.0.1" - fast-glob "^3.3.0" - ignore "^5.2.4" - merge2 "^1.4.1" - slash "^4.0.0" - globby@^8: version "8.0.2" resolved "https://registry.yarnpkg.com/globby/-/globby-8.0.2.tgz#5697619ccd95c5275dbb2d6faa42087c1a941d8d" @@ -13778,21 +8820,6 @@ globby@^8: pify "^3.0.0" slash "^1.0.0" -google-auth-library@^3.0.0, google-auth-library@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-3.1.2.tgz#ff2f88cd5cd2118a57bd3d5ad3c093c8837fc350" - integrity sha512-cDQMzTotwyWMrg5jRO7q0A4TL/3GWBgO7I7q5xGKNiiFf9SmGY/OJ1YsLMgI2MVHHsEGyrqYnbnmV1AE+Z6DnQ== - dependencies: - base64-js "^1.3.0" - fast-text-encoding "^1.0.0" - gaxios "^1.2.1" - gcp-metadata "^1.0.0" - gtoken "^2.3.2" - https-proxy-agent "^2.2.1" - jws "^3.1.5" - lru-cache "^5.0.0" - semver "^5.5.0" - google-auth-library@^7.14.0: version "7.14.1" resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-7.14.1.tgz#e3483034162f24cc71b95c8a55a210008826213c" @@ -13808,27 +8835,7 @@ google-auth-library@^7.14.0: jws "^4.0.0" lru-cache "^6.0.0" -google-gax@^0.25.0: - version "0.25.6" - resolved "https://registry.yarnpkg.com/google-gax/-/google-gax-0.25.6.tgz#5ea5c743933ba957da63951bc828aef91fb69340" - integrity sha512-+CVtOSLQt42mwVvJJirhBiAvWsp8zKeb9zW5Wy3wyvb3VG9OugHzZpwvYO9D4yNPPspe7L9CpIs80I5nUJlS8w== - dependencies: - "@grpc/grpc-js" "^0.3.0" - "@grpc/proto-loader" "^0.4.0" - duplexify "^3.6.0" - google-auth-library "^3.0.0" - google-proto-files "^0.20.0" - grpc "^1.16.0" - grpc-gcp "^0.1.1" - is-stream-ended "^0.1.4" - lodash.at "^4.6.0" - lodash.has "^4.5.2" - protobufjs "^6.8.8" - retry-request "^4.0.0" - semver "^6.0.0" - walkdir "^0.3.2" - -google-gax@^2.0.1, google-gax@^2.24.1: +google-gax@^2.24.1: version "2.30.5" resolved "https://registry.yarnpkg.com/google-gax/-/google-gax-2.30.5.tgz#e836f984f3228900a8336f608c83d75f9cb73eff" integrity sha512-Jey13YrAN2hfpozHzbtrwEfEHdStJh1GwaQ2+Akh1k0Tv/EuNVSuBtHZoKSBm5wBMvNsxTsEIZ/152NrYyZgxQ== @@ -13852,49 +8859,12 @@ google-libphonenumber@^3.2.27: resolved "https://registry.yarnpkg.com/google-libphonenumber/-/google-libphonenumber-3.2.32.tgz#63c48a9c247b64a3bc2eec21bdf3fcfbf2e148c0" integrity sha512-mcNgakausov/B/eTgVeX8qc8IwWjRrupk9UzZZ/QDEvdh5fAjE7Aa211bkZpZj42zKkeS6MTT8avHUwjcLxuGQ== -google-p12-pem@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-1.0.5.tgz#0b4721cdfc818759d884f0c62803518decdaf0d0" - integrity sha512-50rTrqYPTPPwlu9TNl/HkJbBENEpbRzTOVLFJ4YWM86njZgXHFy+FP+tLRSd9m132Li9Dqi27Z3KIWDEv5y+EA== - dependencies: - node-forge "^0.10.0" - pify "^4.0.0" - google-p12-pem@^3.1.3: version "3.1.4" - resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-3.1.4.tgz#123f7b40da204de4ed1fbf2fd5be12c047fc8b3b" - integrity sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg== - dependencies: - node-forge "^1.3.1" - -google-proto-files@^0.20.0: - version "0.20.0" - resolved "https://registry.yarnpkg.com/google-proto-files/-/google-proto-files-0.20.0.tgz#dfcd1635a0c3f00f49ca057462cf369108ff4b5e" - integrity sha512-ORU+XhOeDv/UPtnCYLkO1ItmfhRCRPR3ZoeVQ7GfVzEs7PVitPIhsYlY5ZzG8XXnsdmtK27ENurfQ1jhAWpZHg== - dependencies: - "@google-cloud/promisify" "^0.4.0" - protobufjs "^6.8.0" - walkdir "^0.3.0" - -googleapis-common@^0.7.0: - version "0.7.2" - resolved "https://registry.yarnpkg.com/googleapis-common/-/googleapis-common-0.7.2.tgz#a694f55d979cb7c2eac21a0e0439af12f9b418ba" - integrity sha512-9DEJIiO4nS7nw0VE1YVkEfXEj8x8MxsuB+yZIpOBULFSN9OIKcUU8UuKgSZFU4lJmRioMfngktrbkMwWJcUhQg== - dependencies: - gaxios "^1.2.2" - google-auth-library "^3.0.0" - pify "^4.0.0" - qs "^6.5.2" - url-template "^2.0.8" - uuid "^3.2.1" - -googleapis@^39.2.0: - version "39.2.0" - resolved "https://registry.yarnpkg.com/googleapis/-/googleapis-39.2.0.tgz#5c81f721e9da2e80cb0b25821ed60d3bc200c3da" - integrity sha512-66X8TG1B33zAt177sG1CoKoYHPP/B66tEpnnSANGCqotMuY5gqSQO8G/0gqHZR2jRgc5CHSSNOJCnpI0SuDxMQ== + resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-3.1.4.tgz#123f7b40da204de4ed1fbf2fd5be12c047fc8b3b" + integrity sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg== dependencies: - google-auth-library "^3.0.0" - googleapis-common "^0.7.0" + node-forge "^1.3.1" gopd@^1.0.1: version "1.0.1" @@ -13922,23 +8892,6 @@ got@12.1.0: p-cancelable "^3.0.0" responselike "^2.0.0" -got@9.6.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" - integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== - dependencies: - "@sindresorhus/is" "^0.14.0" - "@szmarczak/http-timer" "^1.1.2" - cacheable-request "^6.0.0" - decompress-response "^3.3.0" - duplexer3 "^0.1.4" - get-stream "^4.1.0" - lowercase-keys "^1.0.1" - mimic-response "^1.0.1" - p-cancelable "^1.0.0" - to-readable-stream "^1.0.0" - url-parse-lax "^3.0.0" - got@^11.8.5: version "11.8.6" resolved "https://registry.yarnpkg.com/got/-/got-11.8.6.tgz#276e827ead8772eddbcfc97170590b841823233a" @@ -13956,27 +8909,7 @@ got@^11.8.5: p-cancelable "^2.0.0" responselike "^2.0.0" -got@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" - integrity sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw== - dependencies: - decompress-response "^3.2.0" - duplexer3 "^0.1.4" - get-stream "^3.0.0" - is-plain-obj "^1.1.0" - is-retry-allowed "^1.0.0" - is-stream "^1.0.0" - isurl "^1.0.0-alpha5" - lowercase-keys "^1.0.0" - p-cancelable "^0.3.0" - p-timeout "^1.1.1" - safe-buffer "^5.0.1" - timed-out "^4.0.0" - url-parse-lax "^1.0.0" - url-to-options "^1.0.1" - -graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.5, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.6, graceful-fs@^4.2.9: +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.5, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.6, graceful-fs@^4.2.9: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -13986,61 +8919,6 @@ grapheme-splitter@^1.0.4: resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== -graphql-tag@^2.11.0, graphql-tag@^2.12.6: - version "2.12.6" - resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.12.6.tgz#d441a569c1d2537ef10ca3d1633b48725329b5f1" - integrity sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg== - dependencies: - tslib "^2.1.0" - -graphql@^14.1.1: - version "14.7.0" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.7.0.tgz#7fa79a80a69be4a31c27dda824dc04dac2035a72" - integrity sha512-l0xWZpoPKpppFzMfvVyFmp9vLN7w/ZZJPefUicMCepfJeQ8sMcztloGYY9DfjVPo6tIUDzU5Hw3MUbIjj9AVVA== - dependencies: - iterall "^1.2.2" - -graphql@^15.3.0: - version "15.8.0" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.8.0.tgz#33410e96b012fa3bdb1091cc99a94769db212b38" - integrity sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw== - -growl@1.10.5: - version "1.10.5" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" - integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== - -grpc-gcp@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/grpc-gcp/-/grpc-gcp-0.1.1.tgz#a11be8a7e7a6edf5f636b44a6a24fb4cc028f71f" - integrity sha512-MAt0Ae9QuL2Lbbt2d+kDta5AxqRD1JVXtBcJuQKp9GeFL5TxPw/hxIyDNyivPjKEXjbG3cBGwSE3CXq6a3KHEQ== - dependencies: - grpc "^1.16.0" - protobufjs "^6.8.8" - -grpc@^1.16.0: - version "1.24.2" - resolved "https://registry.yarnpkg.com/grpc/-/grpc-1.24.2.tgz#76d047bfa7b05b607cbbe3abb99065dcefe0c099" - integrity sha512-EG3WH6AWMVvAiV15d+lr+K77HJ/KV/3FvMpjKjulXHbTwgDZkhkcWbwhxFAoTdxTkQvy0WFcO3Nog50QBbHZWw== - dependencies: - "@types/bytebuffer" "^5.0.40" - lodash.camelcase "^4.3.0" - lodash.clone "^4.5.0" - nan "^2.13.2" - node-pre-gyp "^0.14.0" - protobufjs "^5.0.3" - -gtoken@^2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-2.3.3.tgz#8a7fe155c5ce0c4b71c886cfb282a9060d94a641" - integrity sha512-EaB49bu/TCoNeQjhCYKI/CurooBKkGxIqFHsWABW0b25fobBYVTMe84A8EBVVZhl8emiUdNypil9huMOTmyAnw== - dependencies: - gaxios "^1.0.4" - google-p12-pem "^1.0.0" - jws "^3.1.5" - mime "^2.2.0" - pify "^4.0.0" - gtoken@^5.0.4: version "5.3.2" resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-5.3.2.tgz#deb7dc876abe002178e0515e383382ea9446d58f" @@ -14050,7 +8928,7 @@ gtoken@^5.0.4: google-p12-pem "^3.1.3" jws "^4.0.0" -handlebars@^4.0.1, handlebars@^4.7.6, handlebars@^4.7.7: +handlebars@^4.7.6, handlebars@^4.7.7: version "4.7.7" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== @@ -14085,11 +8963,6 @@ has-bigints@^1.0.1, has-bigints@^1.0.2: resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== -has-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - integrity sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA== - has-flag@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" @@ -14117,23 +8990,11 @@ has-proto@^1.0.1: resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== -has-symbol-support-x@^1.4.1: - version "1.4.2" - resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" - integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== - -has-symbols@^1.0.0, has-symbols@^1.0.2, has-symbols@^1.0.3: +has-symbols@^1.0.2, has-symbols@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== -has-to-string-tag-x@^1.2.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" - integrity sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw== - dependencies: - has-symbol-support-x "^1.4.1" - has-tostringtag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" @@ -14141,7 +9002,7 @@ has-tostringtag@^1.0.0: dependencies: has-symbols "^1.0.2" -has-unicode@^2.0.0, has-unicode@^2.0.1: +has-unicode@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== @@ -14177,7 +9038,7 @@ has-values@^1.0.0: is-number "^3.0.0" kind-of "^4.0.0" -has@^1.0.3, has@~1.0.3: +has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== @@ -14193,11 +9054,6 @@ hash-base@^3.0.0: readable-stream "^3.6.0" safe-buffer "^5.2.0" -hash-stream-validation@^0.2.1: - version "0.2.4" - resolved "https://registry.yarnpkg.com/hash-stream-validation/-/hash-stream-validation-0.2.4.tgz#ee68b41bf822f7f44db1142ec28ba9ee7ccb7512" - integrity sha512-Gjzu0Xn7IagXVkSu9cSFuK1fqzwtLwFhNhVL8IFJijRNMgUttFbBSIAzKuSIrsFMO1+g1RlsoN49zPIbwPDMGQ== - hash.js@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846" @@ -14221,34 +9077,6 @@ hasown@^2.0.0: dependencies: function-bind "^1.1.2" -hdkey@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/hdkey/-/hdkey-2.1.0.tgz#755b30b73f54e93c31919c1b2f19205a8e57cb92" - integrity sha512-i9Wzi0Dy49bNS4tXXeGeu0vIcn86xXdPQUpEYg+SO1YiO8HtomjmmRMaRyqL0r59QfcD4PfVbSF3qmsWFwAemA== - dependencies: - bs58check "^2.1.2" - ripemd160 "^2.0.2" - safe-buffer "^5.1.1" - secp256k1 "^4.0.0" - -hdkey@^0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/hdkey/-/hdkey-0.7.1.tgz#caee4be81aa77921e909b8d228dd0f29acaee632" - integrity sha512-ADjIY5Bqdvp3Sh+SLSS1W3/gTJnlDwwM3UsM/5sHPojc4pLf6X3MfMMiTa96MgtADNhTPa+E+SAKMtqdv1zUfw== - dependencies: - coinstring "^2.0.0" - secp256k1 "^3.0.1" - -he@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - integrity sha512-z/GDPjlRMNOa2XJiB4em8wJpuuBfrFOlYKTZxtpkdr1uPdibHI8rYA3MY0KDObpVyaes0e/aunid/t88ZI2EKA== - -he@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== - header-case@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/header-case/-/header-case-1.0.1.tgz#9535973197c144b09613cd65d317ef19963bd02d" @@ -14257,14 +9085,6 @@ header-case@^1.0.0: no-case "^2.2.0" upper-case "^1.1.3" -header-case@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/header-case/-/header-case-2.0.4.tgz#5a42e63b55177349cf405beb8d775acabb92c063" - integrity sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q== - dependencies: - capital-case "^1.0.4" - tslib "^2.0.3" - hexer@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/hexer/-/hexer-1.5.0.tgz#b86ce808598e8a9d1892c571f3cedd86fc9f0653" @@ -14294,14 +9114,7 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -homedir-polyfill@^1.0.0, homedir-polyfill@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" - integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== - dependencies: - parse-passwd "^1.0.0" - -hosted-git-info@^2.1.4, hosted-git-info@^2.6.0: +hosted-git-info@^2.1.4: version "2.8.9" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== @@ -14342,16 +9155,6 @@ htmlparser2@^8.0.1: domutils "^3.0.1" entities "^4.4.0" -http-basic@^8.1.1: - version "8.1.3" - resolved "https://registry.yarnpkg.com/http-basic/-/http-basic-8.1.3.tgz#a7cabee7526869b9b710136970805b1004261bbf" - integrity sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw== - dependencies: - caseless "^0.12.0" - concat-stream "^1.6.2" - http-response-object "^3.0.1" - parse-cache-control "^1.0.1" - http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" @@ -14380,17 +9183,6 @@ http-errors@2.0.0: statuses "2.0.1" toidentifier "1.0.1" -http-errors@^1.7.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c" - integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.1" - http-https@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" @@ -14414,13 +9206,6 @@ http-proxy-agent@^5.0.0: agent-base "6" debug "4" -http-response-object@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/http-response-object/-/http-response-object-3.0.2.tgz#7f435bb210454e4360d074ef1f989d5ea8aa9810" - integrity sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA== - dependencies: - "@types/node" "^10.0.3" - http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" @@ -14446,14 +9231,6 @@ http2-wrapper@^2.1.10: quick-lru "^5.1.1" resolve-alpn "^1.2.0" -https-proxy-agent@^2.2.1: - version "2.2.4" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b" - integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg== - dependencies: - agent-base "^4.3.0" - debug "^3.1.0" - https-proxy-agent@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" @@ -14472,16 +9249,6 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== -human-signals@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-3.0.1.tgz#c740920859dafa50e5a3222da9d3bf4bb0e5eef5" - integrity sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ== - -humanize-duration@^3.17.0: - version "3.28.0" - resolved "https://registry.yarnpkg.com/humanize-duration/-/humanize-duration-3.28.0.tgz#f79770c0bec34d3bfd4899338cc40643bc04df72" - integrity sha512-jMAxraOOmHuPbffLVDKkEKi/NeG8dMqP8lGRd6Tbf7JgAeG33jjgPWDbXXU7ypCI0o+oNKJFgbSB9FKVdWNI2A== - humanize-duration@^3.29.0: version "3.30.0" resolved "https://registry.yarnpkg.com/humanize-duration/-/humanize-duration-3.30.0.tgz#9be623d331116583ff90aeb6ccfdc2e79d6d7372" @@ -14504,7 +9271,7 @@ hyperlinker@^1.0.0: resolved "https://registry.yarnpkg.com/hyperlinker/-/hyperlinker-1.0.0.tgz#23dc9e38a206b208ee49bc2d6c8ef47027df0c0e" integrity sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ== -iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4: +iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -14535,7 +9302,7 @@ ieee754@^1.1.13, ieee754@^1.1.4, ieee754@^1.2.1: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== -ignore-walk@3.0.4, ignore-walk@^3.0.1: +ignore-walk@3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.4.tgz#c9a09f69b7c7b479a5d74ac1a3c0d4236d2a6335" integrity sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ== @@ -14554,35 +9321,12 @@ ignore@^3.3.5: resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== -ignore@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" - integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== - -ignore@^5.0.4, ignore@^5.1.1, ignore@^5.1.4, ignore@^5.2.0, ignore@^5.2.4: +ignore@^5.0.4, ignore@^5.1.1, ignore@^5.1.4, ignore@^5.2.0: version "5.2.4" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== -immediate@3.3.0, immediate@^3.2.3: - version "3.3.0" - resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266" - integrity sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q== - -immediate@~3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" - integrity sha512-RrGCXRm/fRVqMIhqXrGEX9rRADavPiDFSoMb/k64i9XMk8uH4r/Omi5Ctierj6XzNecwDbO4WuFbDD1zmpl3Tg== - -import-fresh@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" - integrity sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg== - dependencies: - caller-path "^2.0.0" - resolve-from "^3.0.0" - -import-fresh@^3.0.0, import-fresh@^3.2.1: +import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== @@ -14636,7 +9380,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -14664,25 +9408,6 @@ init-package-json@^3.0.2: validate-npm-package-license "^3.0.4" validate-npm-package-name "^4.0.0" -inquirer@^6.2.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" - integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== - dependencies: - ansi-escapes "^3.2.0" - chalk "^2.4.2" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^3.0.3" - figures "^2.0.0" - lodash "^4.17.12" - mute-stream "0.0.7" - run-async "^2.2.0" - rxjs "^6.4.0" - string-width "^2.1.0" - strip-ansi "^5.1.0" - through "^2.3.6" - inquirer@^7.0.5: version "7.3.3" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003" @@ -14723,7 +9448,7 @@ inquirer@^8.2.4: through "^2.3.6" wrap-ansi "^7.0.0" -internal-slot@^1.0.4, internal-slot@^1.0.5: +internal-slot@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== @@ -14737,13 +9462,6 @@ interpret@^1.0.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== -invariant@2: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" @@ -14769,14 +9487,6 @@ ipaddr.js@1.9.1: resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== -is-absolute@^0.2.2: - version "0.2.6" - resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-0.2.6.tgz#20de69f3db942ef2d87b9c2da36f172235b1b5eb" - integrity sha512-7Kr05z5LkcOpoMvxHN1PC11WbPabdNFmMYYo0eZvWu3BfVS0T03yoqYDczoCBx17xqk2x1XAZrcKiFVL88jxlQ== - dependencies: - is-relative "^0.2.1" - is-windows "^0.2.0" - is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" @@ -14791,7 +9501,7 @@ is-accessor-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" -is-arguments@^1.0.4, is-arguments@^1.1.1: +is-arguments@^1.0.4: version "1.1.1" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== @@ -14825,13 +9535,6 @@ is-bigint@^1.0.1: dependencies: has-bigints "^1.0.1" -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - is-boolean-object@^1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" @@ -14840,12 +9543,12 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-buffer@^1.0.2, is-buffer@^1.1.5: +is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-buffer@^2.0.2, is-buffer@^2.0.5, is-buffer@~2.0.3: +is-buffer@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== @@ -14922,35 +9625,11 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-data-descriptor "^1.0.0" kind-of "^6.0.2" -is-directory@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" - integrity sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw== - is-docker@^2.0.0, is-docker@^2.1.1: version "2.2.1" resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== -is-dotdir@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/is-dotdir/-/is-dotdir-0.1.0.tgz#da1e5464f59fc3a83c1d822b5ace091b45fe6b31" - integrity sha512-o5DMjqNJBNvA8Irv57+jeEFf/15AP29DCpG157wABj6XjBBzJSJ8NpYsRwNSTkjBc9xw2OVGAMiqmef3EMpMvA== - dependencies: - dotdir-regex "^0.1.0" - -is-dotfile@^1.0.0, is-dotfile@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" - integrity sha512-9YclgOGtN/f8zx0Pr4FQYMdibBiTaH3sn52vjYip4ZSf6C4/6RfTEZ+MR4GvKhCxdPh21Bg42/WL55f6KSnKpg== - -is-equal-shallow@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" - integrity sha512-0EygVC5qPvIyb+gSz7zdD5/AAoS6Qrx1e//6N4yv4oNm30kqvdmG66oZFWVlQHUWe5OjP08FuTw2IdT0EOTcYA== - dependencies: - is-primitive "^2.0.0" - is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -14963,21 +9642,11 @@ is-extendable@^1.0.1: dependencies: is-plain-object "^2.0.4" -is-extglob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - integrity sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww== - is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== -is-fn@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fn/-/is-fn-1.0.0.tgz#9543d5de7bcf5b08a22ec8a20bae6e286d510d8c" - integrity sha512-XoFPJQmsAShb3jEQRfzf2rqXavq7fIqF/jOekp308JlThqrODnMpweVSGilKTCXELfLhltGP2AGgbQGVP8F1dg== - is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" @@ -15012,18 +9681,6 @@ is-generator-function@^1.0.7: dependencies: has-tostringtag "^1.0.0" -is-glob@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-1.1.3.tgz#b4c64b8303d39114492a460d364ccfb0d3c0a045" - integrity sha512-tKLBgs6hhR6eI0mq8M2b91eUynY27ydu7MbY68IxVE1mlX2r7vbvXJ5qNz/KgDGMXAqMis156hxfvQVh7DcYTA== - -is-glob@^2.0.0, is-glob@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - integrity sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg== - dependencies: - is-extglob "^1.0.0" - is-glob@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" @@ -15031,7 +9688,7 @@ is-glob@^3.1.0: dependencies: is-extglob "^2.1.0" -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: +is-glob@^4.0.0, is-glob@^4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -15048,11 +9705,6 @@ is-interactive@^1.0.0: resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== -is-interactive@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-2.0.0.tgz#40c57614593826da1100ade6059778d597f16e90" - integrity sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ== - is-lambda@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" @@ -15065,16 +9717,6 @@ is-lower-case@^1.1.0: dependencies: lower-case "^1.1.0" -is-map@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127" - integrity sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg== - -is-natural-number@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" - integrity sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ== - is-negative-zero@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" @@ -15087,13 +9729,6 @@ is-number-object@^1.0.4: dependencies: has-tostringtag "^1.0.0" -is-number@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - integrity sha512-QUzH43Gfb9+5yckcrSA0VBDwEtDUchrk4F6tfJZQuNzDJbEDB9cZNzSfXGQ1jqmdDY/kl41lUOWM9syA8z8jlg== - dependencies: - kind-of "^3.0.2" - is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" @@ -15101,37 +9736,22 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" -is-number@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" - integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== - is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-obj@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg== - is-obj@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== -is-object@^1.0.1, is-object@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.2.tgz#a56552e1c665c9e950b4a025461da87e72f86fcf" - integrity sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA== - is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== -is-plain-obj@^2.0.0, is-plain-obj@^2.1.0: +is-plain-obj@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== @@ -15148,17 +9768,7 @@ is-plain-object@^5.0.0: resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== -is-posix-bracket@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" - integrity sha512-Yu68oeXJ7LeWNmZ3Zov/xg/oDBnBK2RNxwYY1ilNJX+tKKZqgPK+qOn/Gs9jEu66KDY9Netf5XLKNGzas/vPfQ== - -is-primitive@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" - integrity sha512-N3w1tFaRfk3UrPfqeRyD+GYDASU3W5VinKhlORy8EWVf/sIdDL9GAcew85XmktCfH+ngG7SRXEVDoO18WMdB/Q== - -is-regex@^1.0.4, is-regex@^1.1.4, is-regex@~1.1.4: +is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== @@ -15166,28 +9776,11 @@ is-regex@^1.0.4, is-regex@^1.1.4, is-regex@~1.1.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-relative@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-0.2.1.tgz#d27f4c7d516d175fb610db84bbeef23c3bc97aa5" - integrity sha512-9AMzjRmLqcue629b4ezEVSK6kJsYJlUIhMcygmYORUgwUNJiavHcC3HkaGx0XYpyVKQSOqFbMEZmW42cY87sYw== - dependencies: - is-unc-path "^0.1.1" - -is-retry-allowed@^1.0.0, is-retry-allowed@^1.1.0: +is-retry-allowed@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4" integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== -is-retry-allowed@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-2.2.0.tgz#88f34cbd236e043e71b6932d09b0c65fb7b4d71d" - integrity sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg== - -is-set@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.2.tgz#90755fa4c2562dc1c5d4024760d6119b94ca18ec" - integrity sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g== - is-shared-array-buffer@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" @@ -15207,7 +9800,7 @@ is-stream-ended@^0.1.4: resolved "https://registry.yarnpkg.com/is-stream-ended/-/is-stream-ended-0.1.4.tgz#f50224e95e06bce0e356d440a4827cd35b267eda" integrity sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw== -is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: +is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ== @@ -15217,11 +9810,6 @@ is-stream@^2.0.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== -is-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" - integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== - is-string@^1.0.5, is-string@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" @@ -15278,23 +9866,11 @@ is-typedarray@^1.0.0, is-typedarray@~1.0.0: resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== -is-unc-path@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-0.1.2.tgz#6ab053a72573c10250ff416a3814c35178af39b9" - integrity sha512-HhLc5VDMH4pu3oMtIuunz/DFQUIoR561kMME3U3Afhj8b7vH085vkIkemrz1kLXCEIuoMAmO3yVmafWdSbGW8w== - dependencies: - unc-path-regex "^0.1.0" - is-unicode-supported@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== -is-unicode-supported@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz#d824984b616c292a2e198207d4a609983842f714" - integrity sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ== - is-upper-case@^1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/is-upper-case/-/is-upper-case-1.1.2.tgz#8d0b1fa7e7933a1e58483600ec7d9661cbaf756f" @@ -15314,17 +9890,7 @@ is-weakref@^1.0.2: dependencies: call-bind "^1.0.2" -is-windows@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-0.1.1.tgz#be310715431cfabccc54ab3951210fa0b6d01abe" - integrity sha512-3wf9CiLayWrH2O5E99jdTwVZyZwVckl+Gz4CkAtjssBPkawQBoPWDEyAHmwZnODQxqYduCBrlGfKQfvE/Mxh+A== - -is-windows@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-0.2.0.tgz#de1aa6d63ea29dd248737b69f1ff8b8002d2108c" - integrity sha512-n67eJYmXbniZB7RF4I/FTjK1s6RPOCTxhYrVYLRaCt3lF0mpWZPKr3T2LSZAqyjQsxR2qMmGYXXzK0YWwcPM1Q== - -is-windows@^1.0.0, is-windows@^1.0.1, is-windows@^1.0.2: +is-windows@^1.0.0, is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== @@ -15361,11 +9927,6 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== -isobject@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-1.0.2.tgz#f0f9b8ce92dd540fa0740882e3835a2e022ec78a" - integrity sha512-WQQgFoML/sLgmhu9zTekYHZUJaPoa/fpVMQ8oxIuOvppzs70DxxyHZdAIjwcuuNDOVtNYsahhqtBbUvKwhRcGw== - isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" @@ -15378,37 +9939,11 @@ isobject@^3.0.0, isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== -isomorphic-fetch@^2.2.0, isomorphic-fetch@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" - integrity sha512-9c4TNAKYXM5PRyVcwUZrF3W09nQ+sO7+jydgs4ZGW9dhsLG2VOlISJABombdQqQRXCwuYG3sYV/puGf5rp0qmA== - dependencies: - node-fetch "^1.0.1" - whatwg-fetch ">=0.10.0" - -isomorphic-fetch@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz#0267b005049046d2421207215d45d6a262b8b8b4" - integrity sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA== - dependencies: - node-fetch "^2.6.1" - whatwg-fetch "^3.4.1" - isomorphic-ws@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz#e5529148912ecb9b451b46ed44d53dae1ce04bbf" integrity sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw== -isomorphic-ws@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc" - integrity sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w== - -isows@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.3.tgz#93c1cf0575daf56e7120bab5c8c448b0809d0d74" - integrity sha512-2cKei4vlmg2cxEjm3wVSqn8pcoRF/LX/wpifuuNquFO4SQmPwarClT+SUCA2lt+l581tTeZIPIZuIDo2jWN1fg== - isstream@0.1.x, isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -15456,83 +9991,6 @@ istanbul-reports@^3.1.3: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -istanbul@^0.4.5: - version "0.4.5" - resolved "https://registry.yarnpkg.com/istanbul/-/istanbul-0.4.5.tgz#65c7d73d4c4da84d4f3ac310b918fb0b8033733b" - integrity sha512-nMtdn4hvK0HjUlzr1DrKSUY8ychprt8dzHOgY2KXsIhHu5PuQQEOTM27gV9Xblyon7aUH/TSFIjRHEODF/FRPg== - dependencies: - abbrev "1.0.x" - async "1.x" - escodegen "1.8.x" - esprima "2.7.x" - glob "^5.0.15" - handlebars "^4.0.1" - js-yaml "3.x" - mkdirp "0.5.x" - nopt "3.x" - once "1.x" - resolve "1.1.x" - supports-color "^3.1.0" - which "^1.1.1" - wordwrap "^1.0.0" - -isurl@^1.0.0-alpha5: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" - integrity sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w== - dependencies: - has-to-string-tag-x "^1.2.0" - is-object "^1.0.1" - -iter-tools@^7.0.2: - version "7.5.1" - resolved "https://registry.yarnpkg.com/iter-tools/-/iter-tools-7.5.1.tgz#0b0253403bf9364335917d562ba7735d19b4c16a" - integrity sha512-YWfjOIj1x3mPY6zB+c1HqnVzOHAVM2iWmNlylvBtSnXC0mnSmCAlmUhfEO4M82m1avdSxe//TlxmLQ3hdj75Cg== - dependencies: - "@babel/runtime" "^7.12.1" - -iterall@^1.2.2: - version "1.3.0" - resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea" - integrity sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg== - -iterate-iterator@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/iterate-iterator/-/iterate-iterator-1.0.2.tgz#551b804c9eaa15b847ea6a7cdc2f5bf1ec150f91" - integrity sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw== - -iterate-value@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/iterate-value/-/iterate-value-1.0.2.tgz#935115bd37d006a52046535ebc8d07e9c9337f57" - integrity sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ== - dependencies: - es-get-iterator "^1.0.2" - iterate-iterator "^1.0.1" - -j6@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/j6/-/j6-1.0.2.tgz#48088acb1c66f610baf2e50b4028d0932f35ed89" - integrity sha512-pKADWYWaJu2traMItqvGo9XUF7/FKUO0SaI7b7ddvsqKhHIsw6Y/CTUvhc0MBSt9M3Q8/ywvQc0+KYqxLJcMnw== - dependencies: - algebrite "^0.2.23" - jStat "^1.5.2" - lodash "^4.16.4" - numeric "^1.2.6" - -jStat@^1.5.2: - version "1.8.6" - resolved "https://registry.yarnpkg.com/jStat/-/jStat-1.8.6.tgz#ab4d465b21f583d37a72ab2f97a300492da7575d" - integrity sha512-Oh/ePZVSoFigme69pHTQudcGh64cpNH9Lz3hBZcRJWLrDqpw7JfuYU9F3dj9py3tBYmHz7og7ZT8hXTNbYq9Rw== - -jackspeak@^2.3.5: - version "2.3.6" - resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" - integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== - dependencies: - "@isaacs/cliui" "^8.0.2" - optionalDependencies: - "@pkgjs/parseargs" "^0.11.0" - jaeger-client@^3.15.0: version "3.19.0" resolved "https://registry.yarnpkg.com/jaeger-client/-/jaeger-client-3.19.0.tgz#9b5bd818ebd24e818616ee0f5cffe1722a53ae6e" @@ -15554,11 +10012,6 @@ jake@^10.8.5: filelist "^1.0.1" minimatch "^3.0.4" -javascript-natural-sort@0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz#f9e2303d4507f6d74355a73664d1440fb5a0ef59" - integrity sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw== - jest-changed-files@^29.5.0: version "29.5.0" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.5.0.tgz#e88786dca8bf2aa899ec4af7644e16d9dcf9b23e" @@ -15936,11 +10389,6 @@ joi@^17.3.0: "@sideway/formula" "^3.0.1" "@sideway/pinpoint" "^2.0.0" -js-sdsl@^4.1.4: - version "4.4.0" - resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.0.tgz#8b437dbe642daa95760400b602378ed8ffea8430" - integrity sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg== - js-sha3@0.5.7, js-sha3@^0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" @@ -15951,25 +10399,12 @@ js-sha3@0.8.0, js-sha3@^0.8.0: resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== -js-sha3@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.7.0.tgz#0a5c57b36f79882573b2d84051f8bb85dd1bd63a" - integrity sha512-Wpks3yBDm0UcL5qlVhwW9Jr9n9i4FfeWBFOOXP5puDS/SiudJGhw7DPyBqn3487qD4F0lsC0q3zxink37f7zeA== - -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: +js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@3.13.1: - version "3.13.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" - integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -js-yaml@3.14.1, js-yaml@3.x, js-yaml@^3.10.0, js-yaml@^3.12.0, js-yaml@^3.13.0, js-yaml@^3.13.1, js-yaml@^3.6.1: +js-yaml@3.14.1, js-yaml@^3.10.0, js-yaml@^3.13.0, js-yaml@^3.13.1, js-yaml@^3.6.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== @@ -15994,13 +10429,6 @@ jsesc@^2.5.1: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== -json-bigint@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-0.3.1.tgz#0c1729d679f580d550899d6a2226c228564afe60" - integrity sha512-DGWnSzmusIreWlEupsUelHrhwmPPE+FiQvg+drKfk2p+bdEYa5mp4PJ8JsCWqae0M2jQNb0HPvnwvf1qOTThzQ== - dependencies: - bignumber.js "^9.0.0" - json-bigint@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-1.0.0.tgz#ae547823ac0cad8398667f8cd9ef4730f5b01ff1" @@ -16008,11 +10436,6 @@ json-bigint@^1.0.0: dependencies: bignumber.js "^9.0.0" -json-buffer@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" - integrity sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ== - json-buffer@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" @@ -16028,73 +10451,16 @@ json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== -json-pointer@^0.6.1: - version "0.6.2" - resolved "https://registry.yarnpkg.com/json-pointer/-/json-pointer-0.6.2.tgz#f97bd7550be5e9ea901f8c9264c9d436a22a93cd" - integrity sha512-vLWcKbOaXlO+jvRy4qNd+TI1QUPZzfJj1tpJ3vAXDych5XJf93ftpUKe5pKCrzyIIwgBJcOcCVRUfqQP25afBw== - dependencies: - foreach "^2.0.4" - -json-rpc-engine@^5.3.0: - version "5.4.0" - resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-5.4.0.tgz#75758609d849e1dba1e09021ae473f3ab63161e5" - integrity sha512-rAffKbPoNDjuRnXkecTjnsE3xLLrb00rEkdgalINhaYVYIxDwWtvYBr9UFbhTvPB1B2qUOLoFd/cV6f4Q7mh7g== - dependencies: - eth-rpc-errors "^3.0.0" - safe-event-emitter "^1.0.1" - -json-rpc-engine@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-6.1.0.tgz#bf5ff7d029e1c1bf20cb6c0e9f348dcd8be5a393" - integrity sha512-NEdLrtrq1jUZyfjkr9OCz9EzCNhnRyWtt1PAnvnhwy6e8XETS0Dtc+ZNCO2gvuAoKsIn2+vCSowXTYE4CkgnAQ== - dependencies: - "@metamask/safe-event-emitter" "^2.0.0" - eth-rpc-errors "^4.0.2" - -json-rpc-error@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/json-rpc-error/-/json-rpc-error-2.0.0.tgz#a7af9c202838b5e905c7250e547f1aff77258a02" - integrity sha512-EwUeWP+KgAZ/xqFpaP6YDAXMtCJi+o/QQpCQFIYyxr01AdADi2y413eM8hSqJcoQym9WMePAJWoaODEJufC4Ug== - dependencies: - inherits "^2.0.1" - -json-rpc-random-id@^1.0.0, json-rpc-random-id@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8" - integrity sha512-RJ9YYNCkhVDBuP4zN5BBtYAzEl03yq/jIIsyif0JY9qyJuQQZNeDK7anAPKKlyEtLSj2s8h6hNh2F8zO5q7ScA== - json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== -json-schema-traverse@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" - integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== - -json-schema-typed@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/json-schema-typed/-/json-schema-typed-7.0.3.tgz#23ff481b8b4eebcd2ca123b4fa0409e66469a2d9" - integrity sha512-7DE8mpG+/fVw+dTpjbxnx47TaMnDfOI1jwft9g1VybltZCduyRQPJPvc+zzKY9WPHxhPWczyFuYa6I8Mw4iU5A== - json-schema@0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== - -json-stable-stringify@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz#e06f23128e0bbe342dc996ed5a19e28b57b580e0" - integrity sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g== - dependencies: - jsonify "^0.0.1" - json-stringify-nice@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz#2c937962b80181d3f317dd39aa323e14f5a60a67" @@ -16105,21 +10471,6 @@ json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== -json-text-sequence@^0.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/json-text-sequence/-/json-text-sequence-0.1.1.tgz#a72f217dc4afc4629fff5feb304dc1bd51a2f3d2" - integrity sha512-L3mEegEWHRekSHjc7+sc8eJhba9Clq1PZ8kMkzf8OxElhXc8O4TS5MwcVlj9aEbm5dr81N90WHC5nAz3UO971w== - dependencies: - delimit-stream "0.1.0" - -json-to-ast@^2.0.3: - version "2.1.0" - resolved "https://registry.yarnpkg.com/json-to-ast/-/json-to-ast-2.1.0.tgz#041a9fcd03c0845036acb670d29f425cea4faaf9" - integrity sha512-W9Lq347r8tA1DfMvAGn9QNcgYm4Wm7Yc+k8e6vezpMnRT+NHbtlxgNBXRVjXe9YM6eTn6+p/MKOlV/aABJcSnQ== - dependencies: - code-error-fragment "0.0.230" - grapheme-splitter "^1.0.4" - json5@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" @@ -16160,21 +10511,11 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" -jsonify@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" - integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== - jsonparse@^1.2.0, jsonparse@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== -jsonpointer@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.1.tgz#2110e0af0900fd37467b5907ecd13a7884a1b559" - integrity sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ== - jsonwebtoken@^8.5.1: version "8.5.1" resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" @@ -16229,7 +10570,7 @@ jwa@^2.0.0: ecdsa-sig-formatter "1.0.11" safe-buffer "^5.0.1" -jws@^3.1.5, jws@^3.2.2: +jws@^3.2.2: version "3.2.2" resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== @@ -16245,14 +10586,6 @@ jws@^4.0.0: jwa "^2.0.0" safe-buffer "^5.0.1" -keccak@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.1.tgz#ae30a0e94dbe43414f741375cff6d64c8bea0bff" - integrity sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA== - dependencies: - node-addon-api "^2.0.0" - node-gyp-build "^4.2.0" - keccak@3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.2.tgz#4c2c6e8c54e04f2670ee49fa734eb9da152206e0" @@ -16289,13 +10622,6 @@ keytar@^7.3.0: node-addon-api "^4.3.0" prebuild-install "^7.0.1" -keyv@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" - integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== - dependencies: - json-buffer "3.0.0" - keyv@^4.0.0: version "4.5.2" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.2.tgz#0e310ce73bf7851ec702f2eaf46ec4e3805cce56" @@ -16303,18 +10629,6 @@ keyv@^4.0.0: dependencies: json-buffer "3.0.1" -kind-of@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-1.1.0.tgz#140a3d2d41a36d2efcfa9377b62c24f8495a5c44" - integrity sha512-aUH6ElPnMGon2/YkxRIigV32MOpTVcoXQ1Oo8aYn40s+sJ3j+0gFZsT8HKDcxNy7Fi9zuquWtGaGAahOdv5p/g== - -kind-of@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-2.0.1.tgz#018ec7a4ce7e3a86cb9141be519d24c8faa981b5" - integrity sha512-0u8i1NZ/mg0b+W3MGGw5I7+6Eib2nx72S/QvXa0hYjEkjTknYmEYQJwGu3mLC0BrhtJjtQafTkyRUQ75Kx0LVg== - dependencies: - is-buffer "^1.0.2" - kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" @@ -16339,13 +10653,6 @@ kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== -klaw-sync@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c" - integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ== - dependencies: - graceful-fs "^4.1.11" - klaw@^1.0.0: version "1.3.1" resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" @@ -16353,11 +10660,6 @@ klaw@^1.0.0: optionalDependencies: graceful-fs "^4.1.9" -kleur@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-2.0.2.tgz#b704f4944d95e255d038f0cb05fb8a602c55a300" - integrity sha512-77XF9iTllATmG9lSlIv0qdQ2BQ/h9t0bJllHlbvsQ0zUWfU7Yi0S8L5JXzPZgkefIiajLmBJJ4BsMJmqcf7oxQ== - kleur@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" @@ -16368,23 +10670,6 @@ kleur@^4.1.5: resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780" integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ== -lazy-cache@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-0.1.0.tgz#d6cd450251d415b70103765f63130a0049a03795" - integrity sha512-WDBCsYgeOSNWVk8t3RYQ63PPnldXNdXg1ZIvPZ53XfueW0CHqmo462o4BmmpSuuxavJAXQl5ogRHVRiAIHti5Q== - dependencies: - ansi-yellow "^0.1.1" - -lazy-cache@^0.2.4: - version "0.2.7" - resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-0.2.7.tgz#7feddf2dcb6edb77d11ef1d117ab5ffdf0ab1b65" - integrity sha512-gkX52wvU/R8DVMMt78ATVPFMJqfW8FPz1GZ1sVHBVQHmu/WvhIWE4cE1GBzhJNFicDeYhnwp6Rl35BcAIM3YOQ== - -lazy-cache@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" - integrity sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ== - lcid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" @@ -16428,18 +10713,6 @@ lerna@^5.5.0: nx ">=14.8.1 < 16" typescript "^3 || ^4" -level-codec@9.0.2, level-codec@^9.0.0: - version "9.0.2" - resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-9.0.2.tgz#fd60df8c64786a80d44e63423096ffead63d8cbc" - integrity sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ== - dependencies: - buffer "^5.6.0" - -level-codec@~7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-7.0.1.tgz#341f22f907ce0f16763f24bddd681e395a0fb8a7" - integrity sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ== - level-concat-iterator@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/level-concat-iterator/-/level-concat-iterator-3.1.0.tgz#5235b1f744bc34847ed65a50548aa88d22e881cf" @@ -16447,102 +10720,6 @@ level-concat-iterator@^3.0.0: dependencies: catering "^2.1.0" -level-concat-iterator@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/level-concat-iterator/-/level-concat-iterator-2.0.1.tgz#1d1009cf108340252cb38c51f9727311193e6263" - integrity sha512-OTKKOqeav2QWcERMJR7IS9CUo1sHnke2C0gkSmcR7QuEtFNLLzHQAvnMw8ykvEcv0Qtkg0p7FOwP1v9e5Smdcw== - -level-errors@^1.0.3: - version "1.1.2" - resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.1.2.tgz#4399c2f3d3ab87d0625f7e3676e2d807deff404d" - integrity sha512-Sw/IJwWbPKF5Ai4Wz60B52yj0zYeqzObLh8k1Tk88jVmD51cJSKWSYpRyhVIvFzZdvsPqlH5wfhp/yxdsaQH4w== - dependencies: - errno "~0.1.1" - -level-errors@^2.0.0, level-errors@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-2.0.1.tgz#2132a677bf4e679ce029f517c2f17432800c05c8" - integrity sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw== - dependencies: - errno "~0.1.1" - -level-errors@~1.0.3: - version "1.0.5" - resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.0.5.tgz#83dbfb12f0b8a2516bdc9a31c4876038e227b859" - integrity sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig== - dependencies: - errno "~0.1.1" - -level-iterator-stream@~1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz#e43b78b1a8143e6fa97a4f485eb8ea530352f2ed" - integrity sha512-1qua0RHNtr4nrZBgYlpV0qHHeHpcRRWTxEZJ8xsemoHAXNL5tbooh4tPEEqIqsbWCAJBmUmkwYK/sW5OrFjWWw== - dependencies: - inherits "^2.0.1" - level-errors "^1.0.3" - readable-stream "^1.0.33" - xtend "^4.0.0" - -level-iterator-stream@~3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz#2c98a4f8820d87cdacab3132506815419077c730" - integrity sha512-nEIQvxEED9yRThxvOrq8Aqziy4EGzrxSZK+QzEFAVuJvQ8glfyZ96GB6BoI4sBbLfjMXm2w4vu3Tkcm9obcY0g== - dependencies: - inherits "^2.0.1" - readable-stream "^2.3.6" - xtend "^4.0.0" - -level-iterator-stream@~4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-4.0.2.tgz#7ceba69b713b0d7e22fcc0d1f128ccdc8a24f79c" - integrity sha512-ZSthfEqzGSOMWoUGhTXdX9jv26d32XJuHz/5YnuHZzH6wldfWMOVwI9TBtKcya4BKTyTt3XVA0A3cF3q5CY30Q== - dependencies: - inherits "^2.0.4" - readable-stream "^3.4.0" - xtend "^4.0.2" - -level-js@^5.0.0: - version "5.0.2" - resolved "https://registry.yarnpkg.com/level-js/-/level-js-5.0.2.tgz#5e280b8f93abd9ef3a305b13faf0b5397c969b55" - integrity sha512-SnBIDo2pdO5VXh02ZmtAyPP6/+6YTJg2ibLtl9C34pWvmtMEmRTWpra+qO/hifkUtBTOtfx6S9vLDjBsBK4gRg== - dependencies: - abstract-leveldown "~6.2.3" - buffer "^5.5.0" - inherits "^2.0.3" - ltgt "^2.1.2" - -level-mem@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/level-mem/-/level-mem-3.0.1.tgz#7ce8cf256eac40f716eb6489654726247f5a89e5" - integrity sha512-LbtfK9+3Ug1UmvvhR2DqLqXiPW1OJ5jEh0a3m9ZgAipiwpSxGj/qaVVy54RG5vAQN1nCuXqjvprCuKSCxcJHBg== - dependencies: - level-packager "~4.0.0" - memdown "~3.0.0" - -level-mem@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/level-mem/-/level-mem-5.0.1.tgz#c345126b74f5b8aa376dc77d36813a177ef8251d" - integrity sha512-qd+qUJHXsGSFoHTziptAKXoLX87QjR7v2KMbqncDXPxQuCdsQlzmyX+gwrEHhlzn08vkf8TyipYyMmiC6Gobzg== - dependencies: - level-packager "^5.0.3" - memdown "^5.0.0" - -level-packager@^5.0.3, level-packager@^5.1.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/level-packager/-/level-packager-5.1.1.tgz#323ec842d6babe7336f70299c14df2e329c18939" - integrity sha512-HMwMaQPlTC1IlcwT3+swhqf/NUO+ZhXVz6TY1zZIIZlIR0YSn8GtAAWmIvKjNY16ZkEg/JcpAuQskxsXqC0yOQ== - dependencies: - encoding-down "^6.3.0" - levelup "^4.3.2" - -level-packager@~4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/level-packager/-/level-packager-4.0.1.tgz#7e7d3016af005be0869bc5fa8de93d2a7f56ffe6" - integrity sha512-svCRKfYLn9/4CoFfi+d8krOtrp6RoX8+xm0Na5cgXMqSyRru0AnDYdLl+YI8u1FyS6gGZ94ILLZDE5dh2but3Q== - dependencies: - encoding-down "~5.0.0" - levelup "^3.0.0" - level-supports@^2.0.1: version "2.1.0" resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-2.1.0.tgz#9af908d853597ecd592293b2fad124375be79c5f" @@ -16553,13 +10730,6 @@ level-supports@^4.0.0: resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-4.0.1.tgz#431546f9d81f10ff0fea0e74533a0e875c08c66a" integrity sha512-PbXpve8rKeNcZ9C1mUicC9auIYFyGpkV9/i6g76tLgANwWhtG2v7I4xNBUlkn3lE2/dZF3Pi0ygYGtLc4RXXdA== -level-supports@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-1.0.1.tgz#2f530a596834c7301622521988e2c36bb77d122d" - integrity sha512-rXM7GYnW8gsl1vedTJIbzOrRv85c/2uCMpiiCzO2fndd06U/kUXEEU9evYn4zFggBOg36IsBW8LzqIpETwwQzg== - dependencies: - xtend "^4.0.2" - level-transcoder@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/level-transcoder/-/level-transcoder-1.0.1.tgz#f8cef5990c4f1283d4c86d949e73631b0bc8ba9c" @@ -16568,56 +10738,6 @@ level-transcoder@^1.0.1: buffer "^6.0.3" module-error "^1.0.1" -level-write-stream@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/level-write-stream/-/level-write-stream-1.0.0.tgz#3f7fbb679a55137c0feb303dee766e12ee13c1dc" - integrity sha512-bBNKOEOMl8msO+uIM9YX/gUO6ckokZ/4pCwTm/lwvs46x6Xs8Zy0sn3Vh37eDqse4mhy4fOMIb/JsSM2nyQFtw== - dependencies: - end-stream "~0.1.0" - -level-ws@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-0.0.0.tgz#372e512177924a00424b0b43aef2bb42496d228b" - integrity sha512-XUTaO/+Db51Uiyp/t7fCMGVFOTdtLS/NIACxE/GHsij15mKzxksZifKVjlXDF41JMUP/oM1Oc4YNGdKnc3dVLw== - dependencies: - readable-stream "~1.0.15" - xtend "~2.1.1" - -level-ws@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-2.0.0.tgz#207a07bcd0164a0ec5d62c304b4615c54436d339" - integrity sha512-1iv7VXx0G9ec1isqQZ7y5LmoZo/ewAsyDHNA8EFDW5hqH2Kqovm33nSFkSdnLLAK+I5FlT+lo5Cw9itGe+CpQA== - dependencies: - inherits "^2.0.3" - readable-stream "^3.1.0" - xtend "^4.0.1" - -level@6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/level/-/level-6.0.1.tgz#dc34c5edb81846a6de5079eac15706334b0d7cd6" - integrity sha512-psRSqJZCsC/irNhfHzrVZbmPYXDcEYhA5TVNwr+V92jF44rbf86hqGp8fiT702FyiArScYIlPSBTDUASCVNSpw== - dependencies: - level-js "^5.0.0" - level-packager "^5.1.0" - leveldown "^5.4.0" - -level@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/level/-/level-8.0.0.tgz#41b4c515dabe28212a3e881b61c161ffead14394" - integrity sha512-ypf0jjAk2BWI33yzEaaotpq7fkOPALKAgDBxggO6Q9HGX2MRXn0wbP1Jn/tJv1gtL867+YOjOB49WaUF3UoJNQ== - dependencies: - browser-level "^1.0.1" - classic-level "^1.2.0" - -leveldown@5.6.0, leveldown@^5.4.0: - version "5.6.0" - resolved "https://registry.yarnpkg.com/leveldown/-/leveldown-5.6.0.tgz#16ba937bb2991c6094e13ac5a6898ee66d3eee98" - integrity sha512-iB8O/7Db9lPaITU1aA2txU/cBEXAt4vWwKQRrrWuS6XDgbP4QZGj9BL2aNbwb002atoQ/lIotJkfyzz+ygQnUQ== - dependencies: - abstract-leveldown "~6.2.1" - napi-macros "~2.0.0" - node-gyp-build "~4.1.0" - leveldown@6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/leveldown/-/leveldown-6.1.0.tgz#7ab1297706f70c657d1a72b31b40323aa612b9ee" @@ -16627,53 +10747,11 @@ leveldown@6.1.0: napi-macros "~2.0.0" node-gyp-build "^4.3.0" -levelup@4.4.0, levelup@^4.3.2: - version "4.4.0" - resolved "https://registry.yarnpkg.com/levelup/-/levelup-4.4.0.tgz#f89da3a228c38deb49c48f88a70fb71f01cafed6" - integrity sha512-94++VFO3qN95cM/d6eBXvd894oJE0w3cInq9USsyQzzoJxmiYzPAocNcuGCPGGjoXqDVJcr3C1jzt1TSjyaiLQ== - dependencies: - deferred-leveldown "~5.3.0" - level-errors "~2.0.0" - level-iterator-stream "~4.0.0" - level-supports "~1.0.0" - xtend "~4.0.0" - -levelup@^1.2.1: - version "1.3.9" - resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.9.tgz#2dbcae845b2bb2b6bea84df334c475533bbd82ab" - integrity sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ== - dependencies: - deferred-leveldown "~1.2.1" - level-codec "~7.0.0" - level-errors "~1.0.3" - level-iterator-stream "~1.3.0" - prr "~1.0.1" - semver "~5.4.1" - xtend "~4.0.0" - -levelup@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/levelup/-/levelup-3.1.1.tgz#c2c0b3be2b4dc316647c53b42e2f559e232d2189" - integrity sha512-9N10xRkUU4dShSRRFTBdNaBxofz+PGaIZO962ckboJZiNmLuhVT6FZ6ZKAsICKfUBO76ySaYU6fJWX/jnj3Lcg== - dependencies: - deferred-leveldown "~4.0.0" - level-errors "~2.0.0" - level-iterator-stream "~3.0.0" - xtend "~4.0.0" - leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== -levn@^0.3.0, levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - libnpmaccess@^6.0.3: version "6.0.4" resolved "https://registry.yarnpkg.com/libnpmaccess/-/libnpmaccess-6.0.4.tgz#2dd158bd8a071817e2207d3b201d37cf1ad6ae6b" @@ -16747,11 +10825,6 @@ load-json-file@^6.2.0: strip-bom "^4.0.0" type-fest "^0.6.0" -load-tsconfig@^0.2.0: - version "0.2.5" - resolved "https://registry.yarnpkg.com/load-tsconfig/-/load-tsconfig-0.2.5.tgz#453b8cd8961bfb912dea77eb6c168fe8cca3d3a1" - integrity sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg== - load-yaml-file@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/load-yaml-file/-/load-yaml-file-0.2.0.tgz#af854edaf2bea89346c07549122753c07372f64d" @@ -16792,18 +10865,6 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" -locate-path@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-7.2.0.tgz#69cb1779bd90b35ab1e771e1f2f89a202c2a8a8a" - integrity sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA== - dependencies: - p-locate "^6.0.0" - -lodash-es@^4.2.1: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" - integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== - lodash._reinterpolate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" @@ -16814,36 +10875,11 @@ lodash.assign@^4.0.3, lodash.assign@^4.0.6: resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" integrity sha512-hFuH8TY+Yji7Eja3mGiuAxBqLagejScbG8GbG0j6o9vzn0YL14My+ktnqtZgFTosKymC9/44wP6s7xyuLfnClw== -lodash.at@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.at/-/lodash.at-4.6.0.tgz#93cdce664f0a1994ea33dd7cd40e23afd11b0ff8" - integrity sha512-GOTh0SEp+Yosnlpjic+8cl2WM9MykorogkGA9xyIFkkObQ3H3kNZqZ+ohuq4K3FrSVo7hMcZBMataJemrxC3BA== - lodash.camelcase@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== -lodash.clone@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-4.5.0.tgz#195870450f5a13192478df4bc3d23d2dea1907b6" - integrity sha512-GhrVeweiTD6uTmmn5hV/lzgCQhccwReIVRLHp7LT4SopOjqEZ5BbX8b5WWEtAKasjmy8hR7ZPwsYlxRCku5odg== - -lodash.debounce@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== - -lodash.get@~4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" - integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ== - -lodash.has@^4.5.2: - version "4.5.2" - resolved "https://registry.yarnpkg.com/lodash.has/-/lodash.has-4.5.2.tgz#d19f4dc1095058cccbe2b0cdf4ee0fe4aa37c862" - integrity sha512-rnYUdIo6xRCJnQmbVFEwcxF144erlD+M3YcJUVesflU9paQaE8p+fJDcIQrlMYbxoANFL+AB9hZrzSBBk5PL+g== - lodash.includes@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" @@ -16889,7 +10925,7 @@ lodash.memoize@4.x: resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== -lodash.merge@^4.6.0, lodash.merge@^4.6.2: +lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== @@ -16899,11 +10935,6 @@ lodash.once@^4.0.0: resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== -lodash.snakecase@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d" - integrity sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw== - lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" @@ -16929,24 +10960,12 @@ lodash.templatesettings@^4.0.0: dependencies: lodash._reinterpolate "^3.0.0" -lodash.values@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-4.3.0.tgz#a3a6c2b0ebecc5c2cba1c17e6e620fe81b53d347" - integrity sha512-r0RwvdCv8id9TUblb/O7rYPwVy6lerCbcawrfdo9iC/1t1wsNMJknO79WNBgwkH0hIeJ08jmvvESbFpNb4jH0Q== - -lodash@^4.16.4, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.2.1: +lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -log-symbols@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" - integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== - dependencies: - chalk "^2.4.2" - -log-symbols@4.1.0, log-symbols@^4.1.0: +log-symbols@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== @@ -16954,26 +10973,6 @@ log-symbols@4.1.0, log-symbols@^4.1.0: chalk "^4.1.0" is-unicode-supported "^0.1.0" -log-symbols@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" - integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== - dependencies: - chalk "^2.0.1" - -log-symbols@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-5.1.0.tgz#a20e3b9a5f53fac6aeb8e2bb22c07cf2c8f16d93" - integrity sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA== - dependencies: - chalk "^5.0.0" - is-unicode-supported "^1.1.0" - -loglevel@^1.6.1, loglevel@^1.6.8: - version "1.8.1" - resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.8.1.tgz#5c621f83d5b48c54ae93b6156353f555963377b4" - integrity sha512-tCRIJM51SHjAayKwC+QAg8hT8vg6z7GSgLJKGvzuPb1Wc+hLzqtuVLxp6/HzSPOozuK+8ErAhy7U/sVzw8Dgfg== - long@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/long/-/long-2.4.0.tgz#9fa180bb1d9500cdc29c4156766a1995e1f4524f" @@ -16989,25 +10988,6 @@ long@^5.0.0: resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1" integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q== -long@~3: - version "3.2.0" - resolved "https://registry.yarnpkg.com/long/-/long-3.2.0.tgz#d821b7138ca1cb581c172990ef14db200b5c474b" - integrity sha512-ZYvPPOMqUwPoDsbJaR10iQJYnMuZhRTvHYl62ErLIEX7RgFlziSBUUvrt3OVfc47QlHHpzPZYP17g3Fv7oeJkg== - -loose-envify@^1.0.0, loose-envify@^1.1.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -loupe@^2.3.1: - version "2.3.6" - resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.6.tgz#76e4af498103c532d1ecc9be102036a21f787b53" - integrity sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA== - dependencies: - get-func-name "^2.0.0" - lower-case-first@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/lower-case-first/-/lower-case-first-1.0.2.tgz#e5da7c26f29a7073be02d52bac9980e5922adfa1" @@ -17020,18 +11000,6 @@ lower-case@^1.1.0, lower-case@^1.1.1, lower-case@^1.1.2: resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" integrity sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA== -lower-case@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" - integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== - dependencies: - tslib "^2.0.3" - -lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== - lowercase-keys@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" @@ -17042,11 +11010,6 @@ lowercase-keys@^3.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-3.0.0.tgz#c5e7d442e37ead247ae9db117a9d0a467c89d4f2" integrity sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ== -"lru-cache@7.10.1 - 7.13.1": - version "7.13.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.13.1.tgz#267a81fbd0881327c46a81c5922606a2cfe336c4" - integrity sha512-CHqbAq7NFlW3RSnoWXLJBxCWaZVBrfa9UEHId2M3AW8iEBurbqduNexEUCGc3SHc6iCYXNJCDi903LajSVAEPQ== - lru-cache@^4.0.1: version "4.1.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" @@ -17055,7 +11018,7 @@ lru-cache@^4.0.1: pseudomap "^1.0.2" yallist "^2.1.2" -lru-cache@^5.0.0, lru-cache@^5.1.1: +lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== @@ -17074,31 +11037,12 @@ lru-cache@^7.4.4, lru-cache@^7.5.1, lru-cache@^7.7.1: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89" integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== -"lru-cache@^9.1.1 || ^10.0.0": - version "10.0.2" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.0.2.tgz#34504678cc3266b09b8dfd6fab4e1515258271b7" - integrity sha512-Yj9mA8fPiVgOUpByoTZO5pNrcl5Yk37FcSHsUINpAsaBIEZIuqcCclDZJCVxqQShDsmYX8QG63svJiTbOATZwg== - dependencies: - semver "^7.3.5" - -ltgt@2.2.1, ltgt@^2.1.2, ltgt@~2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" - integrity sha512-AI2r85+4MquTw9ZYqabu4nMwy9Oftlfa/e/52t9IjtfG+mGBbTNdAoZ3RQKLHR6r0wQnwZnPIEh/Ya6XTWAKNA== - lunr@^2.3.9: version "2.3.9" resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== -make-dir@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" - integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== - dependencies: - pify "^3.0.0" - -make-dir@^2.0.0, make-dir@^2.1.0: +make-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== @@ -17154,7 +11098,7 @@ map-age-cleaner@^0.1.1: dependencies: p-defer "^1.0.0" -map-cache@^0.2.0, map-cache@^0.2.2: +map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg== @@ -17176,40 +11120,11 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" -markdown-table@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.3.tgz#9fcb69bcfdb8717bfd0398c6ec2d93036ef8de60" - integrity sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q== - marked@^1.1.1: version "1.2.9" resolved "https://registry.yarnpkg.com/marked/-/marked-1.2.9.tgz#53786f8b05d4c01a2a5a76b7d1ec9943d29d72dc" integrity sha512-H8lIX2SvyitGX+TRdtS06m1jHMijKN/XjfH6Ooii9fvxMlh8QdqBfBDkGUpMWH2kQNrtixjzYUa3SH8ROTgRRw== -math-random@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c" - integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A== - -mathjs@^5.0.4: - version "5.10.3" - resolved "https://registry.yarnpkg.com/mathjs/-/mathjs-5.10.3.tgz#e998885f932ea8886db8b40f7f5b199f89b427f1" - integrity sha512-ySjg30BC3dYjQm73ILZtwcWzFJde0VU6otkXW/57IjjuYRa3Qaf0Kb8pydEuBZYtqW2OxreAtsricrAmOj3jIw== - dependencies: - complex.js "2.0.11" - decimal.js "10.2.0" - escape-latex "1.2.0" - fraction.js "4.0.12" - javascript-natural-sort "0.7.1" - seed-random "2.2.0" - tiny-emitter "2.1.0" - typed-function "1.1.0" - -mcl-wasm@^0.7.1: - version "0.7.9" - resolved "https://registry.yarnpkg.com/mcl-wasm/-/mcl-wasm-0.7.9.tgz#c1588ce90042a8700c3b60e40efb339fc07ab87f" - integrity sha512-iJIUcQWA88IJB/5L15GnJVnSQJmf/YaxxV6zRavv83HILHaJQb6y0iFyDMdDO0gN8X37tdxmAOrH/P8B6RB8sQ== - md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -17233,51 +11148,6 @@ mem@^4.0.0: mimic-fn "^2.0.0" p-is-promise "^2.0.0" -memdown@1.4.1, memdown@^1.0.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.4.1.tgz#b4e4e192174664ffbae41361aa500f3119efe215" - integrity sha512-iVrGHZB8i4OQfM155xx8akvG9FIj+ht14DX5CQkCTG4EHzZ3d3sgckIf/Lm9ivZalEsFuEVnWv2B2WZvbrro2w== - dependencies: - abstract-leveldown "~2.7.1" - functional-red-black-tree "^1.0.1" - immediate "^3.2.3" - inherits "~2.0.1" - ltgt "~2.2.0" - safe-buffer "~5.1.1" - -memdown@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/memdown/-/memdown-5.1.0.tgz#608e91a9f10f37f5b5fe767667a8674129a833cb" - integrity sha512-B3J+UizMRAlEArDjWHTMmadet+UKwHd3UjMgGBkZcKAxAYVPS9o0Yeiha4qvz7iGiL2Sb3igUft6p7nbFWctpw== - dependencies: - abstract-leveldown "~6.2.1" - functional-red-black-tree "~1.0.1" - immediate "~3.2.3" - inherits "~2.0.1" - ltgt "~2.2.0" - safe-buffer "~5.2.0" - -memdown@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/memdown/-/memdown-3.0.0.tgz#93aca055d743b20efc37492e9e399784f2958309" - integrity sha512-tbV02LfZMWLcHcq4tw++NuqMO+FZX8tNJEiD2aNRm48ZZusVg5N8NART+dmBkepJVye986oixErf7jfXboMGMA== - dependencies: - abstract-leveldown "~5.0.0" - functional-red-black-tree "~1.0.1" - immediate "~3.2.3" - inherits "~2.0.1" - ltgt "~2.2.0" - safe-buffer "~5.1.1" - -memory-level@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/memory-level/-/memory-level-1.0.0.tgz#7323c3fd368f9af2f71c3cd76ba403a17ac41692" - integrity sha512-UXzwewuWeHBz5krr7EvehKcmLFNoXxGcvuYhC41tRnkrTbJohtS7kVn9akmgirtRygg+f7Yjsfi8Uu5SGSQ4Og== - dependencies: - abstract-level "^1.0.0" - functional-red-black-tree "^1.0.1" - module-error "^1.0.1" - memorystream@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" @@ -17317,7 +11187,7 @@ meow@^8.0.0: type-fest "^0.18.0" yargs-parser "^20.2.3" -merge-descriptors@1.0.1, merge-descriptors@~1.0.0: +merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== @@ -17332,33 +11202,6 @@ merge2@^1.2.3, merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -merkle-patricia-tree@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-4.0.0.tgz#b95500a2a188a813eae18b175b34d9f439b92a62" - integrity sha512-OnI0iUvc5G66ZJgSB7PnuU6Pnk9QADMcBgua7YhNm8gbQJq5Hbiv9U9hQRe3mEM1KEfbqrdTC+x33bTewF+oCA== - dependencies: - "@types/levelup" "^3.1.1" - ethereumjs-util "^7.0.2" - level-mem "^5.0.1" - level-ws "^2.0.0" - readable-stream "^3.6.0" - rlp "^2.2.4" - semaphore-async-await "^1.5.1" - -merkle-patricia-tree@^2.1.2, merkle-patricia-tree@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz#982ca1b5a0fde00eed2f6aeed1f9152860b8208a" - integrity sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g== - dependencies: - async "^1.4.2" - ethereumjs-util "^5.0.0" - level-ws "0.0.0" - levelup "^1.2.1" - memdown "^1.0.0" - readable-stream "^2.0.0" - rlp "^2.0.0" - semaphore ">=1.0.1" - methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" @@ -17369,25 +11212,6 @@ micro-ftch@^0.3.1: resolved "https://registry.yarnpkg.com/micro-ftch/-/micro-ftch-0.3.1.tgz#6cb83388de4c1f279a034fb0cf96dfc050853c5f" integrity sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg== -micromatch@^2.3.11, micromatch@^2.3.7: - version "2.3.11" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" - integrity sha512-LnU2XFEk9xxSJ6rfgAry/ty5qwUTyHYOBU0g4R6tIw5ljwgGIBmiKhRWLw5NpMOnrgUNcDJ4WMp8rl3sYVHLNA== - dependencies: - arr-diff "^2.0.0" - array-unique "^0.2.1" - braces "^1.8.2" - expand-brackets "^0.1.4" - extglob "^0.3.1" - filename-regex "^2.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.1" - kind-of "^3.0.2" - normalize-path "^2.0.1" - object.omit "^2.0.0" - parse-glob "^3.0.4" - regex-cache "^0.4.2" - micromatch@^3.1.10: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" @@ -17415,36 +11239,12 @@ micromatch@^4.0.2, micromatch@^4.0.4: braces "^3.0.2" picomatch "^2.3.1" -micromatch@jonschlinkert/micromatch#2.2.0: - version "2.2.0" - resolved "https://codeload.github.com/jonschlinkert/micromatch/tar.gz/5017fd78202e04c684cc31d3c2fb1f469ea222ff" - dependencies: - arr-diff "^1.0.1" - array-unique "^0.2.1" - braces "^1.8.0" - expand-brackets "^0.1.1" - extglob "^0.3.0" - filename-regex "^2.0.0" - is-glob "^1.1.3" - kind-of "^1.1.0" - object.omit "^1.1.0" - parse-glob "^3.0.1" - regex-cache "^0.4.2" - -miller-rabin@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== - dependencies: - bn.js "^4.0.0" - brorand "^1.0.1" - -mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": +mime-db@1.52.0: version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.0.8, mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34: +mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -17456,41 +11256,16 @@ mime@1.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mime@^2.2.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" - integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== - -mimic-fn@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== - mimic-fn@^2.0.0, mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -mimic-fn@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-3.1.0.tgz#65755145bbf3e36954b949c16450427451d5ca74" - integrity sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ== - -mimic-fn@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" - integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== - -mimic-response@^1.0.0, mimic-response@^1.0.1: +mimic-response@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== -mimic-response@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43" - integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== - mimic-response@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" @@ -17525,13 +11300,6 @@ minimalistic-crypto-utils@^1.0.1: dependencies: brace-expansion "^1.1.7" -minimatch@3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - minimatch@3.0.5: version "3.0.5" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.5.tgz#4da8f1290ee0f0f8e83d60ca69f8f134068604a3" @@ -17539,13 +11307,6 @@ minimatch@3.0.5: dependencies: brace-expansion "^1.1.7" -minimatch@5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" - integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== - dependencies: - brace-expansion "^2.0.1" - minimatch@^5.0.1: version "5.1.6" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" @@ -17553,13 +11314,6 @@ minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" -minimatch@^9.0.1: - version "9.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" - integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== - dependencies: - brace-expansion "^2.0.1" - minimist-options@4.1.0, minimist-options@^4.0.2: version "4.1.0" resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" @@ -17569,12 +11323,7 @@ minimist-options@4.1.0, minimist-options@^4.0.2: is-plain-obj "^1.1.0" kind-of "^6.0.3" -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha512-miQKw5Hv4NS1Psg2517mV4e4dYNaO3++hjAvLOAzKqZ61rH8NS1SK+vbfBWZ5PY/Me/bEWhUwqMghEW5Fb9T7Q== - -minimist@^1.1.0, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.6, minimist@~1.2.7: +minimist@^1.1.0, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.6: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -17646,11 +11395,6 @@ minipass@^4.0.0: resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.2.8.tgz#f0010f64393ecfc1d1ccb5f582bcaf45f48e1a3a" integrity sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ== -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0": - version "7.0.4" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" - integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== - minizlib@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" @@ -17674,14 +11418,6 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mixin-object@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/mixin-object/-/mixin-object-2.0.1.tgz#4fb949441dab182540f1fe035ba60e1947a5e57e" - integrity sha512-ALGF1Jt9ouehcaXaHhn6t1yGWRqGaHkPFndtFVHfZXOvkIZ/yoGaSi0AHVTafb3ZBGg4dr/bDwnaEKqCXzchMA== - dependencies: - for-in "^0.1.3" - is-extendable "^0.1.1" - mixme@^0.5.1: version "0.5.9" resolved "https://registry.yarnpkg.com/mixme/-/mixme-0.5.9.tgz#a5a58e17354632179ff3ce5b0fc130899c8ba81c" @@ -17713,21 +11449,7 @@ mkdirp@*: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.0.tgz#758101231418bda24435c0888a91d9bd91f1372d" integrity sha512-7+JDnNsyCvZXoUJdkMR0oUE2AmAdsNXGTmRbiOjYIwQ6q+bL6NwrozGQdPcmYaNcrhH37F50HHBUzoaBV6FITQ== -mkdirp@0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha512-SknJC52obPfGQPnjIkXbmA6+5H15E+fR+E4iR2oQ3zzCLbd7/ONua69R/Gw7AgkTLsRG+r5fzksYwWe1AgTyWA== - dependencies: - minimist "0.0.8" - -mkdirp@0.5.5: - version "0.5.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== - dependencies: - minimist "^1.2.5" - -mkdirp@0.5.x, mkdirp@^0.5.1, mkdirp@^0.5.5, mkdirp@~0.5.1: +mkdirp@^0.5.1, mkdirp@^0.5.5, mkdirp@~0.5.1: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== @@ -17739,138 +11461,6 @@ mkdirp@^1.0.3, mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mocha@10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.1.0.tgz#dbf1114b7c3f9d0ca5de3133906aea3dfc89ef7a" - integrity sha512-vUF7IYxEoN7XhQpFLxQAEMtE4W91acW4B6En9l97MwE9stL1A9gusXfoHZCLVHDUJ/7V5+lbCM6yMqzo5vNymg== - dependencies: - ansi-colors "4.1.1" - browser-stdout "1.3.1" - chokidar "3.5.3" - debug "4.3.4" - diff "5.0.0" - escape-string-regexp "4.0.0" - find-up "5.0.0" - glob "7.2.0" - he "1.2.0" - js-yaml "4.1.0" - log-symbols "4.1.0" - minimatch "5.0.1" - ms "2.1.3" - nanoid "3.3.3" - serialize-javascript "6.0.0" - strip-json-comments "3.1.1" - supports-color "8.1.1" - workerpool "6.2.1" - yargs "16.2.0" - yargs-parser "20.2.4" - yargs-unparser "2.0.0" - -mocha@8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-8.0.1.tgz#fe01f0530362df271aa8f99510447bc38b88d8ed" - integrity sha512-vefaXfdYI8+Yo8nPZQQi0QO2o+5q9UIMX1jZ1XMmK3+4+CQjc7+B0hPdUeglXiTlr8IHMVRo63IhO9Mzt6fxOg== - dependencies: - ansi-colors "4.1.1" - browser-stdout "1.3.1" - chokidar "3.3.1" - debug "3.2.6" - diff "4.0.2" - escape-string-regexp "1.0.5" - find-up "4.1.0" - glob "7.1.6" - growl "1.10.5" - he "1.2.0" - js-yaml "3.13.1" - log-symbols "3.0.0" - minimatch "3.0.4" - ms "2.1.2" - object.assign "4.1.0" - promise.allsettled "1.0.2" - serialize-javascript "3.0.0" - strip-json-comments "3.0.1" - supports-color "7.1.0" - which "2.0.2" - wide-align "1.1.3" - workerpool "6.0.0" - yargs "13.3.2" - yargs-parser "13.1.2" - yargs-unparser "1.6.0" - -mocha@^10.2.0: - version "10.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.2.0.tgz#1fd4a7c32ba5ac372e03a17eef435bd00e5c68b8" - integrity sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg== - dependencies: - ansi-colors "4.1.1" - browser-stdout "1.3.1" - chokidar "3.5.3" - debug "4.3.4" - diff "5.0.0" - escape-string-regexp "4.0.0" - find-up "5.0.0" - glob "7.2.0" - he "1.2.0" - js-yaml "4.1.0" - log-symbols "4.1.0" - minimatch "5.0.1" - ms "2.1.3" - nanoid "3.3.3" - serialize-javascript "6.0.0" - strip-json-comments "3.1.1" - supports-color "8.1.1" - workerpool "6.2.1" - yargs "16.2.0" - yargs-parser "20.2.4" - yargs-unparser "2.0.0" - -mocha@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" - integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== - dependencies: - browser-stdout "1.3.1" - commander "2.15.1" - debug "3.1.0" - diff "3.5.0" - escape-string-regexp "1.0.5" - glob "7.1.2" - growl "1.10.5" - he "1.1.1" - minimatch "3.0.4" - mkdirp "0.5.1" - supports-color "5.4.0" - -mocha@^7.1.1: - version "7.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-7.2.0.tgz#01cc227b00d875ab1eed03a75106689cfed5a604" - integrity sha512-O9CIypScywTVpNaRrCAgoUnJgozpIofjKUYmJhiCIJMiuYnLI6otcb1/kpW9/n/tJODHGZ7i8aLQoDVsMtOKQQ== - dependencies: - ansi-colors "3.2.3" - browser-stdout "1.3.1" - chokidar "3.3.0" - debug "3.2.6" - diff "3.5.0" - escape-string-regexp "1.0.5" - find-up "3.0.0" - glob "7.1.3" - growl "1.10.5" - he "1.2.0" - js-yaml "3.13.1" - log-symbols "3.0.0" - minimatch "3.0.4" - mkdirp "0.5.5" - ms "2.1.1" - node-environment-flags "1.0.6" - object.assign "4.1.0" - strip-json-comments "2.0.1" - supports-color "6.0.0" - which "1.3.1" - wide-align "1.1.3" - yargs "13.3.2" - yargs-parser "13.1.2" - yargs-unparser "1.6.0" - mock-fs@^4.1.0: version "4.14.0" resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.14.0.tgz#ce5124d2c601421255985e6e94da80a7357b1b18" @@ -17894,17 +11484,12 @@ module-details-from-path@^1.0.3: resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b" integrity sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A== -module-error@^1.0.1, module-error@^1.0.2: +module-error@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/module-error/-/module-error-1.0.2.tgz#8d1a48897ca883f47a45816d4fb3e3c6ba404d86" integrity sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA== -module-not-found-error@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/module-not-found-error/-/module-not-found-error-1.0.1.tgz#cf8b4ff4f29640674d6cdd02b0e3bc523c2bbdc0" - integrity sha512-pEk4ECWQXV6z2zjhRZUongnLJNUeGQJ3w6OQ5ctGwD+i5o93qjRQUk2Rt6VdNeu3sEP0AB4LcfvdebpxBRVr4g== - -moment@^2.10.6, moment@^2.19.3, moment@^2.22.1: +moment@^2.19.3, moment@^2.22.1: version "2.29.4" resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== @@ -17919,11 +11504,6 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== -ms@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== - ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" @@ -17941,13 +11521,6 @@ msal@^1.0.2: dependencies: tslib "^1.9.3" -multi-progress@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/multi-progress/-/multi-progress-2.0.0.tgz#29ccb42cf24874b1c6384f03127ce5dff7b22f2c" - integrity sha512-ArGgS/Qib/X2FWfE6CVpic+Z0C9kQuhiK9HQtz5pcCfsXwMzoNnXP6FJlplNAMsJuoLtWA8bAoPV36ezT2IFGw== - dependencies: - progress "^1.1.8" - multibase@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.7.0.tgz#1adfc1c50abe05eefeb5091ac0c2728d6b84581b" @@ -18010,11 +11583,6 @@ multimatch@^5.0.0: arrify "^2.0.1" minimatch "^3.0.4" -mute-stream@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" - integrity sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ== - mute-stream@0.0.8, mute-stream@~0.0.4: version "0.0.8" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" @@ -18029,25 +11597,7 @@ mv@~2: ncp "~2.0.0" rimraf "~2.4.0" -mythxjs@^1.3.11: - version "1.3.13" - resolved "https://registry.yarnpkg.com/mythxjs/-/mythxjs-1.3.13.tgz#b27ec4170307a3f3bd3943e7e8628c2eb070d09d" - integrity sha512-dqFLPjEVxj99WJFwLEA4ULNXL992bfth4W9t63V6B/LQbPxHqOvGShbSaHblt/giaMi7mPLcd4WIgk2lBpzFlw== - dependencies: - axios "^0.25.0" - chai-as-promised "^7.1.1" - jsonwebtoken "^8.5.1" - -mz@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" - integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== - dependencies: - any-promise "^1.0.0" - object-assign "^4.0.1" - thenify-all "^1.0.0" - -nan@^2.13.2, nan@^2.14.0, nan@^2.2.1: +nan@^2.14.0, nan@^2.2.1: version "2.17.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb" integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== @@ -18062,11 +11612,6 @@ nano-json-stream-parser@^0.1.2: resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" integrity sha512-9MqxMH/BSJC7dnLsEMPyfN5Dvoo49IsPFYMcHw3Bcfc2kN0lpHRBSzlMSVx4HGyJ7s9B31CyBTVehWJoQ8Ctew== -nanoid@3.3.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" - integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== - nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -18089,11 +11634,6 @@ napi-build-utils@^1.0.1: resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806" integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg== -napi-macros@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/napi-macros/-/napi-macros-2.2.2.tgz#817fef20c3e0e40a963fbf7b37d1600bd0201044" - integrity sha512-hmEVtAGYzVQpCKdbQea4skABsdXW4RUh5t5mJ2zzqowJS2OyXZTU1KhDVFhx+NlWZ4ap9mqR9TcDO3LTTttd+g== - napi-macros@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/napi-macros/-/napi-macros-2.0.0.tgz#2b6bae421e7b96eb687aa6c77a7858640670001b" @@ -18114,15 +11654,6 @@ ncp@~2.0.0: resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3" integrity sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA== -needle@^2.2.1: - version "2.9.1" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.9.1.tgz#22d1dffbe3490c2b83e301f7709b6736cd8f2684" - integrity sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ== - dependencies: - debug "^3.2.6" - iconv-lite "^0.4.4" - sax "^1.2.4" - negotiator@0.6.3, negotiator@^0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" @@ -18131,14 +11662,7 @@ negotiator@0.6.3, negotiator@^0.6.3: neo-async@^2.6.0: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" - integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== - -neodoc@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/neodoc/-/neodoc-2.0.2.tgz#ad00b30b9758379dcd3cf752a0659bacbab2c4fb" - integrity sha512-NAppJ0YecKWdhSXFYCHbo6RutiX8vOt/Jo3l46mUg6pQlpJNaqc5cGxdrW2jITQm5JIYySbFVPDl3RrREXNyPw== - dependencies: - ansi-regex "^2.0.0" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== next-tick@^1.1.0: version "1.1.0" @@ -18157,21 +11681,6 @@ no-case@^2.2.0, no-case@^2.3.2: dependencies: lower-case "^1.1.1" -no-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" - integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== - dependencies: - lower-case "^2.0.2" - tslib "^2.0.3" - -node-abi@^2.21.0: - version "2.30.1" - resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.30.1.tgz#c437d4b1fe0e285aaf290d45b45d4d7afedac4cf" - integrity sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w== - dependencies: - semver "^5.4.1" - node-abi@^3.3.0: version "3.40.0" resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.40.0.tgz#51d8ed44534f70ff1357dfbc3a89717b1ceac1b4" @@ -18179,11 +11688,6 @@ node-abi@^3.3.0: dependencies: semver "^7.3.5" -node-abort-controller@^3.0.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-3.1.1.tgz#a94377e964a9a37ac3976d848cb5c765833b8548" - integrity sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ== - node-addon-api@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" @@ -18204,14 +11708,6 @@ node-domexception@^1.0.0: resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== -node-environment-flags@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.6.tgz#a30ac13621f6f7d674260a54dede048c3982c088" - integrity sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw== - dependencies: - object.getownpropertydescriptors "^2.0.3" - semver "^5.7.0" - node-fetch@2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" @@ -18224,15 +11720,7 @@ node-fetch@2.6.7: dependencies: whatwg-url "^5.0.0" -node-fetch@^1.0.1: - version "1.7.3" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" - integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== - dependencies: - encoding "^0.1.11" - is-stream "^1.0.1" - -node-fetch@^2.2.0, node-fetch@^2.3.0, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7, node-fetch@^2.6.9: +node-fetch@^2.6.1, node-fetch@^2.6.7, node-fetch@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6" integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg== @@ -18248,21 +11736,11 @@ node-fetch@^3.3.0: fetch-blob "^3.1.4" formdata-polyfill "^4.0.10" -node-forge@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" - integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA== - node-forge@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== -node-gyp-build@4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3" - integrity sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q== - node-gyp-build@4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.4.0.tgz#42e99687ce87ddeaf3a10b99dc06abc11021f3f4" @@ -18273,11 +11751,6 @@ node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== -node-gyp-build@~4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.1.1.tgz#d7270b5d86717068d114cc57fff352f96d745feb" - integrity sha512-dSq1xmcPDKPZ2EED2S6zw/b9NKsqzXRE6dVr8TVQnI3FJOTteUMuqF3Qqs6LZg+mLGYJWqQzMbIjMtJqTv87nQ== - node-gyp@^9.0.0: version "9.3.1" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-9.3.1.tgz#1e19f5f290afcc9c46973d68700cbd21a96192e4" @@ -18294,15 +11767,6 @@ node-gyp@^9.0.0: tar "^6.1.2" which "^2.0.2" -node-hid@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/node-hid/-/node-hid-2.1.1.tgz#f83c8aa0bb4e6758b5f7383542477da93f67359d" - integrity sha512-Skzhqow7hyLZU93eIPthM9yjot9lszg9xrKxESleEs05V2NcbUptZc5HFqzjOkSmL0sFlZFr3kmvaYebx06wrw== - dependencies: - bindings "^1.5.0" - node-addon-api "^3.0.2" - prebuild-install "^6.0.0" - node-hid@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/node-hid/-/node-hid-2.1.2.tgz#3145fa86ed4336a402a71e9f372c54213b88797c" @@ -18317,59 +11781,16 @@ node-int64@^0.4.0: resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== -node-interval-tree@^1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/node-interval-tree/-/node-interval-tree-1.3.3.tgz#15ffb904cde08270214acace8dc7653e89ae32b7" - integrity sha512-K9vk96HdTK5fEipJwxSvIIqwTqr4e3HRJeJrNxBSeVMNSC/JWARRaX7etOLOuTmrRMeOI/K5TCJu3aWIwZiNTw== - dependencies: - shallowequal "^1.0.2" - -node-pre-gyp@^0.14.0: - version "0.14.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83" - integrity sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA== - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4.4.2" - node-releases@^2.0.8: version "2.0.10" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.10.tgz#c311ebae3b6a148c89b1813fd7c4d3c024ef537f" integrity sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w== -nofilter@^1.0.3, nofilter@^1.0.4: +nofilter@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/nofilter/-/nofilter-1.0.4.tgz#78d6f4b6a613e7ced8b015cec534625f7667006e" integrity sha512-N8lidFp+fCz+TD51+haYdbDGrcBWwuHX40F5+z0qkUjMJ5Tp+rdSuAkMJ9N9eoolDlEVTf6u5icM+cNKkKW2mA== -noncharacters@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/noncharacters/-/noncharacters-1.1.0.tgz#af33df30fd50ed3c53cd202258f25ada90b540d2" - integrity sha512-U69XzMNq7UQXR27xT17tkQsHPsLc+5W9yfXvYzVCwFxghVf+7VttxFnCKFMxM/cHD+/QIyU009263hxIIurj4g== - -nopt@3.x: - version "3.0.6" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - integrity sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg== - dependencies: - abbrev "1" - -nopt@^4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48" - integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg== - dependencies: - abbrev "1" - osenv "^0.1.4" - nopt@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" @@ -18414,29 +11835,24 @@ normalize-package-data@^4.0.0: semver "^7.3.5" validate-npm-package-license "^3.0.4" -normalize-path@^2.0.1, normalize-path@^2.1.1: +normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" integrity sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w== dependencies: remove-trailing-separator "^1.0.1" -normalize-path@^3.0.0, normalize-path@~3.0.0: +normalize-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== -normalize-url@^4.1.0: - version "4.5.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" - integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== - normalize-url@^6.0.1: version "6.1.0" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== -npm-bundled@^1.0.1, npm-bundled@^1.1.1: +npm-bundled@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.2.tgz#944c78789bd739035b70baa2ca5cc32b8d860bc1" integrity sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ== @@ -18486,15 +11902,6 @@ npm-package-arg@^9.0.0, npm-package-arg@^9.0.1: semver "^7.3.5" validate-npm-package-name "^4.0.0" -npm-packlist@^1.1.6: - version "1.4.8" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e" - integrity sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A== - dependencies: - ignore-walk "^3.0.1" - npm-bundled "^1.0.1" - npm-normalize-package-bin "^1.0.1" - npm-packlist@^5.1.0, npm-packlist@^5.1.1: version "5.1.3" resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-5.1.3.tgz#69d253e6fd664b9058b85005905012e00e69274b" @@ -18549,23 +11956,6 @@ npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" -npm-run-path@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.1.0.tgz#bc62f7f3f6952d9894bd08944ba011a6ee7b7e00" - integrity sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q== - dependencies: - path-key "^4.0.0" - -npmlog@^4.0.1, npmlog@^4.0.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - npmlog@^6.0.0, npmlog@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-6.0.2.tgz#c8166017a42f2dea92d6453168dd865186a70830" @@ -18596,11 +11986,6 @@ number-to-bn@1.7.0: bn.js "4.11.6" strip-hex-prefix "1.0.0" -numeric@^1.2.6: - version "1.2.6" - resolved "https://registry.yarnpkg.com/numeric/-/numeric-1.2.6.tgz#765b02bef97988fcf880d4eb3f36b80fa31335aa" - integrity sha512-avBiDAP8siMa7AfJgYyuxw1oyII4z2sswS23+O+ZfV28KrtNzy0wxUFwi4f3RyM4eeeXNs1CThxR7pb5QQcMiw== - nx@15.9.2, "nx@>=14.8.1 < 16": version "15.9.2" resolved "https://registry.yarnpkg.com/nx/-/nx-15.9.2.tgz#d7ace1e5ae64a47f1b553dc5da08dbdd858bde96" @@ -18657,12 +12042,7 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" - integrity sha512-jHP15vXVGeVh1HuaA2wY6lxk+whK/x4KBG88VXeRma7CCun7iGD5qPc4eYykQ9sdQvg8jkwFKsSxHln2ybW3xQ== - -object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@^4, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== @@ -18681,46 +12061,26 @@ object-hash@^3.0.0: resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== -object-inspect@^1.12.3, object-inspect@^1.9.0, object-inspect@~1.12.3: - version "1.12.3" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" - integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== - object-inspect@^1.13.1: version "1.13.1" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== -object-is@^1.0.1: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" - integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" +object-inspect@^1.9.0: + version "1.12.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== -object-keys@^1.0.11, object-keys@^1.1.1: +object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object-keys@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" - integrity sha512-ncrLw+X55z7bkl5PnUvHwFK9FcGuFYo9gtjws2XtSzL+aZ8tm830P60WJ0dSmFVaSalWieW5MD7kEdnXda9yJw== - object-treeify@^1.1.4: version "1.1.33" resolved "https://registry.yarnpkg.com/object-treeify/-/object-treeify-1.1.33.tgz#f06fece986830a3cba78ddd32d4c11d1f76cdf40" integrity sha512-EFVjAYfzWqWsBMRHPMAXLCDIJnpMhdWAqR7xG6M6a2cs6PMFpl/+Z20w9zDW4vkxOFfddegBKq9Rehd0bxWE7A== -object-visit@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-0.1.0.tgz#b1bb6749f228ee76e0c42f3851d28a14d233ce26" - integrity sha512-gPvtDz6xoiDNPMp3e/5sQGua8cgevJULRMdrX9dcgFbeaTuqGOW3g4OgrLragDA6NSfvS2iNBXrs8CWgBQq83A== - dependencies: - isobject "^1.0.0" - object-visit@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" @@ -18728,16 +12088,6 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" -object.assign@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" - integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== - dependencies: - define-properties "^1.1.2" - function-bind "^1.1.1" - has-symbols "^1.0.0" - object-keys "^1.0.11" - object.assign@^4.1.4: version "4.1.4" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" @@ -18748,33 +12098,6 @@ object.assign@^4.1.4: has-symbols "^1.0.3" object-keys "^1.1.1" -object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.6: - version "2.1.6" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.6.tgz#5e5c384dd209fa4efffead39e3a0512770ccc312" - integrity sha512-lq+61g26E/BgHv0ZTFgRvi7NMEPuAxLkFU7rukXjc/AlwH4Am5xXVnIXy3un1bg/JPbXHrixRkK1itUzzPiIjQ== - dependencies: - array.prototype.reduce "^1.0.5" - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.21.2" - safe-array-concat "^1.0.0" - -object.omit@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-1.1.0.tgz#9d17ea16778e5057deba7752c6f55f1496829e94" - integrity sha512-oc6HJYjJhqPa0AsywIBlKNVd9ctu6lrDwr/N4HSpa3FKD1l3cF5pdgdLHm8Fn0zSKGKTKGwVOdoTTgUh1FQkKw== - dependencies: - for-own "^0.1.3" - isobject "^1.0.0" - -object.omit@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" - integrity sha512-UiAM5mhmIuKLsOvrL+B0U2d1hXHF3bFYWIuH1LMpuV2EJEHG1Ntz06PgLEHjm6VFd87NpH8rastvPoyv6UW2fA== - dependencies: - for-own "^0.1.4" - is-extendable "^0.1.1" - object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" @@ -18782,13 +12105,6 @@ object.pick@^1.3.0: dependencies: isobject "^3.0.1" -oboe@2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.4.tgz#20c88cdb0c15371bb04119257d4fdd34b0aa49f6" - integrity sha512-ymBJ4xSC6GBXLT9Y7lirj+xbqBLa+jADGJldGEYG7u8sZbS9GyG+u1Xk9c5cbriKwSpCg41qUhPjvU5xOpvIyQ== - dependencies: - http-https "^1.0.0" - oboe@2.1.5: version "2.1.5" resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.5.tgz#5554284c543a2266d7a38f17e073821fbde393cd" @@ -18801,15 +12117,6 @@ obuf@~1.1.2: resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== -omni-fetch@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/omni-fetch/-/omni-fetch-0.2.3.tgz#56a6f46ad170b6d978982cca5bd1c6b70597a58d" - integrity sha512-PezYE0Vhm5+/TffAWNjuHz8cuUKgPBgC601EBW/jUyXrCsJPlgtd/CekUvyT+TgKZupl9FQuPhwALrYsUuEbgA== - dependencies: - "@types/isomorphic-fetch" "0.0.31" - "@types/node" "^6.0.52" - caw "^1.2.0" - on-finished@2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" @@ -18817,20 +12124,13 @@ on-finished@2.4.1: dependencies: ee-first "1.1.1" -once@1.x, once@^1.3.0, once@^1.3.1, once@^1.4.0: +once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" -onetime@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - integrity sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ== - dependencies: - mimic-fn "^1.0.0" - onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" @@ -18838,14 +12138,7 @@ onetime@^5.1.0, onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" -onetime@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4" - integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== - dependencies: - mimic-fn "^4.0.0" - -open@^7.0.0, open@^7.4.2: +open@^7.0.0: version "7.4.2" resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== @@ -18867,40 +12160,6 @@ opentracing@^0.14.4: resolved "https://registry.yarnpkg.com/opentracing/-/opentracing-0.14.7.tgz#25d472bd0296dc0b64d7b94cbc995219031428f5" integrity sha512-vz9iS7MJ5+Bp1URw8Khvdyw1H/hGvzHWlKQ7eRrQojSCDL1/SrWfrY9QebLw97n2deyRtzHRC3MkQfVNUCo91Q== -openzeppelin-solidity@^2.5.0: - version "2.5.1" - resolved "https://registry.yarnpkg.com/openzeppelin-solidity/-/openzeppelin-solidity-2.5.1.tgz#1cdcce30c4c6a7b6625dab62ccd0440a813ab597" - integrity sha512-oCGtQPLOou4su76IMr4XXJavy9a8OZmAXeUZ8diOdFznlL/mlkIlYr7wajqCzH4S47nlKPS7m0+a2nilCTpVPQ== - -optionator@^0.8.1, optionator@^0.8.2: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - 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" - -optjs@~3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/optjs/-/optjs-3.2.2.tgz#69a6ce89c442a44403141ad2f9b370bd5bb6f4ee" - integrity sha512-f8lTJm4LKirX+45xsFhuRNjA4f46QVLQKfGoNH7e2AEWS+24eM4XNH4pQ8Tw2LISCIvbST/wNcLdtgvgcqVaxA== - -ora@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/ora/-/ora-3.4.0.tgz#bf0752491059a3ef3ed4c85097531de9fdbcd318" - integrity sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg== - dependencies: - chalk "^2.4.2" - cli-cursor "^2.1.0" - cli-spinners "^2.0.0" - log-symbols "^2.2.0" - strip-ansi "^5.2.0" - wcwidth "^1.0.1" - ora@^5.4.1: version "5.4.1" resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" @@ -18916,31 +12175,6 @@ ora@^5.4.1: strip-ansi "^6.0.0" wcwidth "^1.0.1" -ora@^6.1.2: - version "6.3.1" - resolved "https://registry.yarnpkg.com/ora/-/ora-6.3.1.tgz#a4e9e5c2cf5ee73c259e8b410273e706a2ad3ed6" - integrity sha512-ERAyNnZOfqM+Ao3RAvIXkYh5joP220yf59gVe2X/cI6SiCxIdi4c9HZKZD8R6q/RDXEje1THBju6iExiSsgJaQ== - dependencies: - chalk "^5.0.0" - cli-cursor "^4.0.0" - cli-spinners "^2.6.1" - is-interactive "^2.0.0" - is-unicode-supported "^1.1.0" - log-symbols "^5.1.0" - stdin-discarder "^0.1.0" - strip-ansi "^7.0.1" - wcwidth "^1.0.1" - -original-require@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/original-require/-/original-require-1.0.1.tgz#0f130471584cd33511c5ec38c8d59213f9ac5e20" - integrity sha512-5vdKMbE58WaE61uVD+PKyh8xdM398UnjPBLotW2sjG5MzHARwta/+NtMBCBA0t2WQblGYBvq5vsiZpWokwno+A== - -os-homedir@^1.0.0, os-homedir@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ== - os-locale@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" @@ -18957,34 +12191,16 @@ os-locale@^3.1.0: lcid "^2.0.0" mem "^4.0.0" -os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: +os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== -osenv@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" - outdent@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/outdent/-/outdent-0.5.0.tgz#9e10982fdc41492bb473ad13840d22f9655be2ff" integrity sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q== -p-cancelable@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" - integrity sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw== - -p-cancelable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" - integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== - p-cancelable@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf" @@ -19043,13 +12259,6 @@ p-limit@^3.0.2, p-limit@^3.1.0: dependencies: yocto-queue "^0.1.0" -p-limit@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-4.0.0.tgz#914af6544ed32bfa54670b061cafcbd04984b644" - integrity sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ== - dependencies: - yocto-queue "^1.0.0" - p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" @@ -19078,13 +12287,6 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" -p-locate@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-6.0.0.tgz#3da9a49d4934b901089dca3302fa65dc5a05c04f" - integrity sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw== - dependencies: - p-limit "^4.0.0" - p-map-series@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-map-series/-/p-map-series-2.1.0.tgz#7560d4c452d9da0c07e692fdbfe6e2c81a2a91f2" @@ -19120,13 +12322,6 @@ p-reduce@^2.0.0, p-reduce@^2.1.0: resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-2.1.0.tgz#09408da49507c6c274faa31f28df334bc712b64a" integrity sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw== -p-timeout@^1.1.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" - integrity sha512-gb0ryzr+K2qFqFv6qi3khoeqMZF/+ajxQipEF6NteZVnvz9tzdsfAVj3lYtn1gAXvH5lfLwfxEII799gt/mRIA== - dependencies: - p-finally "^1.0.0" - p-timeout@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe" @@ -19151,11 +12346,6 @@ p-waterfall@^2.1.1: dependencies: p-reduce "^2.0.0" -packet-reader@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-1.0.0.tgz#9238e5480dedabacfe1fe3f2771063f164157d74" - integrity sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ== - pacote@^13.0.3, pacote@^13.6.1: version "13.6.2" resolved "https://registry.yarnpkg.com/pacote/-/pacote-13.6.2.tgz#0d444ba3618ab3e5cd330b451c22967bbd0ca48a" @@ -19190,14 +12380,6 @@ param-case@^2.1.0: dependencies: no-case "^2.2.0" -param-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" - integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A== - dependencies: - dot-case "^3.0.4" - tslib "^2.0.3" - parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -19205,27 +12387,6 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse-asn1@^5.0.0, parse-asn1@^5.1.6: - version "5.1.6" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" - integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== - dependencies: - asn1.js "^5.2.0" - browserify-aes "^1.0.0" - evp_bytestokey "^1.0.0" - pbkdf2 "^3.0.3" - safe-buffer "^5.1.1" - -parse-cache-control@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parse-cache-control/-/parse-cache-control-1.0.1.tgz#8eeab3e54fa56920fe16ba38f77fa21aacc2d74e" - integrity sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg== - -parse-code-context@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/parse-code-context/-/parse-code-context-1.0.0.tgz#718c295c593d0d19a37f898473268cc75e98de1e" - integrity sha512-OZQaqKaQnR21iqhlnPfVisFjBWjhnMl5J9MgbP8xC+EwoVqbXrq78lp+9Zb3ahmLzrIX5Us/qbvBnaS3hkH6OA== - parse-conflict-json@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/parse-conflict-json/-/parse-conflict-json-2.0.2.tgz#3d05bc8ffe07d39600dc6436c6aefe382033d323" @@ -19235,33 +12396,6 @@ parse-conflict-json@^2.0.1: just-diff "^5.0.1" just-diff-apply "^5.2.0" -parse-filepath@^0.6.1: - version "0.6.3" - resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-0.6.3.tgz#38e17a73e5e4e6776bae9506fc3ccb14bc3a2b80" - integrity sha512-/8L5NPcGFMlZZ05LhvyKDQkCb8nX/5DPad9ZGvXrpAyGfk4Fop0PCEyCnwnB7PgnSW2JLCSId0ZNrBo7iAhXYQ== - dependencies: - is-absolute "^0.2.2" - map-cache "^0.2.0" - -parse-gitignore@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/parse-gitignore/-/parse-gitignore-0.2.0.tgz#98706d09f0f93ee86348b721ffee0606bc093d74" - integrity sha512-NB3206JVaagRmgpQCWymcXHd+bZyVxACtgehEL49jDptryTqGcDWo7YroucBXKePj9lGYz3guQVZIV/gqrsaOw== - dependencies: - ends-with "^0.2.0" - is-glob "^2.0.0" - starts-with "^1.0.0" - -parse-glob@^3.0.1, parse-glob@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" - integrity sha512-FC5TeK0AwXzq3tUBFtH74naWkPQCEWs4K+xMxWZBlKDWu0bVHXGZa+KKqxKidd7xwhdZ19ZNuF2uO1M/r196HA== - dependencies: - glob-base "^0.3.0" - is-dotfile "^1.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.0" - parse-headers@^2.0.0: version "2.0.5" resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.5.tgz#069793f9356a54008571eb7f9761153e6c770da9" @@ -19292,11 +12426,6 @@ parse-json@^5.0.0, parse-json@^5.2.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" -parse-passwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" - integrity sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q== - parse-path@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/parse-path/-/parse-path-7.0.0.tgz#605a2d58d0a749c8594405d8cc3a2bf76d16099b" @@ -19326,12 +12455,12 @@ parse5@^7.0.0: dependencies: entities "^4.4.0" -parseurl@^1.3.3, parseurl@~1.3.3: +parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== -pascal-case@^2.0.0, pascal-case@^2.0.1: +pascal-case@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-2.0.1.tgz#2d578d3455f660da65eca18ef95b4e0de912761e" integrity sha512-qjS4s8rBOJa2Xm0jmxXiyh1+OFf6ekCWOvUaRgAQSktzlTbMotS0nmG9gyYAybCWBcuP4fsBeRCKNwGBnMe2OQ== @@ -19339,14 +12468,6 @@ pascal-case@^2.0.0, pascal-case@^2.0.1: camel-case "^3.0.0" upper-case-first "^1.1.0" -pascal-case@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb" - integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g== - dependencies: - no-case "^3.0.4" - tslib "^2.0.3" - pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" @@ -19360,26 +12481,6 @@ password-prompt@^1.0.7, password-prompt@^1.1.2: ansi-escapes "^3.1.0" cross-spawn "^6.0.5" -patch-package@^6.2.2: - version "6.5.1" - resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.5.1.tgz#3e5d00c16997e6160291fee06a521c42ac99b621" - integrity sha512-I/4Zsalfhc6bphmJTlrLoOcAF87jcxko4q0qsv4bGcurbr8IskEOtdnt9iCmsQVGL1B+iUhSQqweyTLJfCF9rA== - dependencies: - "@yarnpkg/lockfile" "^1.1.0" - chalk "^4.1.2" - cross-spawn "^6.0.5" - find-yarn-workspace-root "^2.0.0" - fs-extra "^9.0.0" - is-ci "^2.0.0" - klaw-sync "^6.0.0" - minimist "^1.2.6" - open "^7.4.2" - rimraf "^2.6.3" - semver "^5.6.0" - slash "^2.0.0" - tmp "^0.0.33" - yaml "^1.10.2" - path-case@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/path-case/-/path-case-2.1.1.tgz#94b8037c372d3fe2906e465bb45e25d226e8eea5" @@ -19387,14 +12488,6 @@ path-case@^2.1.0: dependencies: no-case "^2.2.0" -path-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/path-case/-/path-case-3.0.4.tgz#9168645334eb942658375c56f80b4c0cb5f82c6f" - integrity sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg== - dependencies: - dot-case "^3.0.4" - tslib "^2.0.3" - path-dirname@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" @@ -19417,21 +12510,11 @@ path-exists@^4.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== -path-exists@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-5.0.0.tgz#a6aad9489200b21fab31e49cf09277e5116fb9e7" - integrity sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ== - path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== -path-is-inside@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w== - path-key@^2.0.0, path-key@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" @@ -19442,24 +12525,11 @@ path-key@^3.0.0, path-key@^3.1.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== -path-key@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" - integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== - path-parse@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -path-scurry@^1.10.1: - version "1.10.1" - resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.1.tgz#9ba6bf5aa8500fe9fd67df4f0d9483b2b0bfc698" - integrity sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ== - dependencies: - lru-cache "^9.1.1 || ^10.0.0" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" @@ -19499,17 +12569,7 @@ path@^0.12.7: process "^0.11.1" util "^0.10.3" -pathe@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.1.tgz#1dd31d382b974ba69809adc9a7a347e65d84829a" - integrity sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q== - -pathval@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" - integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== - -pbkdf2@^3.0.17, pbkdf2@^3.0.3, pbkdf2@^3.0.9: +pbkdf2@^3.0.17, pbkdf2@^3.0.9: version "3.1.2" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== @@ -19520,21 +12580,11 @@ pbkdf2@^3.0.17, pbkdf2@^3.0.3, pbkdf2@^3.0.9: safe-buffer "^5.0.1" sha.js "^2.4.8" -pend@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg== - performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== -pg-connection-string@0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7" - integrity sha512-i0NV/CrSkFTaiOQs9AGy3tq0dkSjtTd4d7DfsjeDVZAA4aIHInwfFEmriNYGGJUfZ5x6IAC/QddoUpUJjQAi0w== - pg-int8@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" @@ -19545,22 +12595,12 @@ pg-numeric@1.0.2: resolved "https://registry.yarnpkg.com/pg-numeric/-/pg-numeric-1.0.2.tgz#816d9a44026086ae8ae74839acd6a09b0636aa3a" integrity sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw== -pg-packet-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pg-packet-stream/-/pg-packet-stream-1.1.0.tgz#e45c3ae678b901a2873af1e17b92d787962ef914" - integrity sha512-kRBH0tDIW/8lfnnOyTwKD23ygJ/kexQVXZs7gEyBljw4FYqimZFxnMMx50ndZ8In77QgfGuItS5LLclC2TtjYg== - -pg-pool@^2.0.10: - version "2.0.10" - resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-2.0.10.tgz#842ee23b04e86824ce9d786430f8365082d81c4a" - integrity sha512-qdwzY92bHf3nwzIUcj+zJ0Qo5lpG/YxchahxIN8+ZVmXqkahKXsnl2aiJPHLYN9o5mB/leG+Xh6XKxtP7e0sjg== - -pg-protocol@*, pg-protocol@^1.2.0: +pg-protocol@*: version "1.6.0" resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.6.0.tgz#4c91613c0315349363af2084608db843502f8833" integrity sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q== -pg-types@^2.1.0, pg-types@^2.2.0: +pg-types@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3" integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA== @@ -19584,33 +12624,12 @@ pg-types@^4.0.1: postgres-interval "^3.0.0" postgres-range "^1.1.1" -pg@^7.18.0: - version "7.18.2" - resolved "https://registry.yarnpkg.com/pg/-/pg-7.18.2.tgz#4e219f05a00aff4db6aab1ba02f28ffa4513b0bb" - integrity sha512-Mvt0dGYMwvEADNKy5PMQGlzPudKcKKzJds/VbOeZJpb6f/pI3mmoXX0JksPgI3l3JPP/2Apq7F36O63J7mgveA== - dependencies: - buffer-writer "2.0.0" - packet-reader "1.0.0" - pg-connection-string "0.1.3" - pg-packet-stream "^1.1.0" - pg-pool "^2.0.10" - pg-types "^2.1.0" - pgpass "1.x" - semver "4.3.2" - -pgpass@1.x: - version "1.0.5" - resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.5.tgz#9b873e4a564bb10fa7a7dbd55312728d422a223d" - integrity sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug== - dependencies: - split2 "^4.1.0" - picocolors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.0.4, picomatch@^2.0.7, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -19625,7 +12644,7 @@ pify@^3.0.0: resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" integrity sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg== -pify@^4.0.0, pify@^4.0.1: +pify@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== @@ -19652,13 +12671,6 @@ pirates@^4.0.4: resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ== -pkg-dir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" - integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== - dependencies: - find-up "^3.0.0" - pkg-dir@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" @@ -19666,33 +12678,11 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -pkg-up@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" - integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA== - dependencies: - find-up "^3.0.0" - -pluralize@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" - integrity sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow== - -pluralize@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" - integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== - pngjs@^3.3.0: version "3.4.0" resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f" integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w== -popper.js@1.14.3: - version "1.14.3" - resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.3.tgz#1438f98d046acf7b4d78cd502bf418ac64d4f095" - integrity sha512-3lmujhsHXzb83+sI0PzfrE3O1XHZG8m8MXNMTupvA6LrM1/nnsiqYaacYc/RIente9VqnTDPztGEM8uvPAMGyg== - posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" @@ -19738,219 +12728,14 @@ postgres-interval@^1.1.0: xtend "^4.0.0" postgres-interval@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-3.0.0.tgz#baf7a8b3ebab19b7f38f07566c7aab0962f0c86a" - integrity sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw== - -postgres-range@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/postgres-range/-/postgres-range-1.1.3.tgz#9ccd7b01ca2789eb3c2e0888b3184225fa859f76" - integrity sha512-VdlZoocy5lCP0c/t66xAfclglEapXPCIVhqqJRncYpvbCgImF0w67aPKfbqUMr72tO2k5q0TdTZwCLjPTI6C9g== - -pouchdb-abstract-mapreduce@7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/pouchdb-abstract-mapreduce/-/pouchdb-abstract-mapreduce-7.3.1.tgz#96ff4a0f41cbe273f3f52fde003b719005a2093c" - integrity sha512-0zKXVFBvrfc1KnN0ggrB762JDmZnUpePHywo9Bq3Jy+L1FnoG7fXM5luFfvv5/T0gEw+ZTIwoocZECMnESBI9w== - dependencies: - pouchdb-binary-utils "7.3.1" - pouchdb-collate "7.3.1" - pouchdb-collections "7.3.1" - pouchdb-errors "7.3.1" - pouchdb-fetch "7.3.1" - pouchdb-mapreduce-utils "7.3.1" - pouchdb-md5 "7.3.1" - pouchdb-utils "7.3.1" - -pouchdb-adapter-leveldb-core@7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/pouchdb-adapter-leveldb-core/-/pouchdb-adapter-leveldb-core-7.3.1.tgz#3c71dce7ff06c2e483d873d7aabc1fded56372ca" - integrity sha512-mxShHlqLMPz2gChrgtA9okV1ogFmQrRAoM/O4EN0CrQWPLXqYtpL1f7sI2asIvFe7SmpnvbLx7kkZyFmLTfwjA== - dependencies: - argsarray "0.0.1" - buffer-from "1.1.2" - double-ended-queue "2.1.0-0" - levelup "4.4.0" - pouchdb-adapter-utils "7.3.1" - pouchdb-binary-utils "7.3.1" - pouchdb-collections "7.3.1" - pouchdb-errors "7.3.1" - pouchdb-json "7.3.1" - pouchdb-md5 "7.3.1" - pouchdb-merge "7.3.1" - pouchdb-utils "7.3.1" - sublevel-pouchdb "7.3.1" - through2 "3.0.2" - -pouchdb-adapter-memory@^7.1.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/pouchdb-adapter-memory/-/pouchdb-adapter-memory-7.3.1.tgz#7be4b0601326cb93eb1141ed910fdfdf40c36616" - integrity sha512-iHdWGJAHONqQv0we3Oi1MYen69ZS8McLW9wUyaAYcWTJnAIIAr2ZM0/TeTDVSHfMUwYqEYk7X8jRtJZEMwLnwg== - dependencies: - memdown "1.4.1" - pouchdb-adapter-leveldb-core "7.3.1" - pouchdb-utils "7.3.1" - -pouchdb-adapter-utils@7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/pouchdb-adapter-utils/-/pouchdb-adapter-utils-7.3.1.tgz#7237cb597f8d337057df15d4859bfe3c881d8832" - integrity sha512-uKLG6dClwTs/sLIJ4WkLAi9wlnDBpOnfyhpeAgOjlOGN/XLz5nKHrA4UJRnURDyc+uv79S9r/Unc4hVpmbSPUw== - dependencies: - pouchdb-binary-utils "7.3.1" - pouchdb-collections "7.3.1" - pouchdb-errors "7.3.1" - pouchdb-md5 "7.3.1" - pouchdb-merge "7.3.1" - pouchdb-utils "7.3.1" - -pouchdb-binary-utils@7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/pouchdb-binary-utils/-/pouchdb-binary-utils-7.3.1.tgz#eea22d9a5f880fcd95062476f4f5484cdf61496f" - integrity sha512-crZJNfAEOnUoRk977Qtmk4cxEv6sNKllQ6vDDKgQrQLFjMUXma35EHzNyIJr1s76J77Q4sqKQAmxz9Y40yHGtw== - dependencies: - buffer-from "1.1.2" - -pouchdb-collate@7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/pouchdb-collate/-/pouchdb-collate-7.3.1.tgz#19d7b87dd173d1c765da8cc9987c5aa9eb24f11f" - integrity sha512-o4gyGqDMLMSNzf6EDTr3eHaH/JRMoqRhdc+eV+oA8u00nTBtr9wD+jypVe2LbgKLJ4NWqx2qVkXiTiQdUFtsLQ== - -pouchdb-collections@7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/pouchdb-collections/-/pouchdb-collections-7.3.1.tgz#4f1819cf4dd6936a422c29f7fa26a9b5dca428f5" - integrity sha512-yUyDqR+OJmtwgExOSJegpBJXDLAEC84TWnbAYycyh+DZoA51Yw0+XVQF5Vh8Ii90/Ut2xo88fmrmp0t6kqom8w== - -pouchdb-debug@^7.1.1: - version "7.2.1" - resolved "https://registry.yarnpkg.com/pouchdb-debug/-/pouchdb-debug-7.2.1.tgz#f5f869f6113c12ccb97cddf5b0a32b6e0e67e961" - integrity sha512-eP3ht/AKavLF2RjTzBM6S9gaI2/apcW6xvaKRQhEdOfiANqerFuksFqHCal3aikVQuDO+cB/cw+a4RyJn/glBw== - dependencies: - debug "3.1.0" - -pouchdb-errors@7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/pouchdb-errors/-/pouchdb-errors-7.3.1.tgz#78be36721e2edc446fac158a236a9218c7bcdb14" - integrity sha512-Zktz4gnXEUcZcty8FmyvtYUYsHskoST05m6H5/E2gg/0mCfEXq/XeyyLkZHaZmqD0ZPS9yNmASB1VaFWEKEaDw== - dependencies: - inherits "2.0.4" - -pouchdb-fetch@7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/pouchdb-fetch/-/pouchdb-fetch-7.3.1.tgz#d54b1807be0f0a5d4b6d06e416c7d54952bbc348" - integrity sha512-205xAtvdHRPQ4fp1h9+RmT9oQabo9gafuPmWsS9aEl3ER54WbY8Vaj1JHZGbU4KtMTYvW7H5088zLS7Nrusuag== - dependencies: - abort-controller "3.0.0" - fetch-cookie "0.11.0" - node-fetch "2.6.7" - -pouchdb-find@^7.0.0: - version "7.3.1" - resolved "https://registry.yarnpkg.com/pouchdb-find/-/pouchdb-find-7.3.1.tgz#07a633d5ee2bd731dae9f991281cd25212088d29" - integrity sha512-AeqUfAVY1c7IFaY36BRT0vIz9r4VTKq/YOWTmiqndOZUQ/pDGxyO2fNFal6NN3PyYww0JijlD377cPvhnrhJVA== - dependencies: - pouchdb-abstract-mapreduce "7.3.1" - pouchdb-collate "7.3.1" - pouchdb-errors "7.3.1" - pouchdb-fetch "7.3.1" - pouchdb-md5 "7.3.1" - pouchdb-selector-core "7.3.1" - pouchdb-utils "7.3.1" - -pouchdb-json@7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/pouchdb-json/-/pouchdb-json-7.3.1.tgz#a80a3060aa2914959e4dca7a4e2022ab20c7119a" - integrity sha512-AyOKsmc85/GtHjMZyEacqzja8qLVfycS1hh1oskR+Bm5PIITX52Fb8zyi0hEetV6VC0yuGbn0RqiLjJxQePeqQ== - dependencies: - vuvuzela "1.0.3" - -pouchdb-mapreduce-utils@7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/pouchdb-mapreduce-utils/-/pouchdb-mapreduce-utils-7.3.1.tgz#f0ac2c8400fbedb705e9226082453ac7d3f2a066" - integrity sha512-oUMcq82+4pTGQ6dtrhgORHOVHZSr6w/5tFIUGlv7RABIDvJarL4snMawADjlpiEwPdiQ/ESG8Fqt8cxqvqsIgg== - dependencies: - argsarray "0.0.1" - inherits "2.0.4" - pouchdb-collections "7.3.1" - pouchdb-utils "7.3.1" - -pouchdb-md5@7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/pouchdb-md5/-/pouchdb-md5-7.3.1.tgz#70fae44f9d27eb4c6a8e7106156b4593d31c1762" - integrity sha512-aDV8ui/mprnL3xmt0gT/81DFtTtJiKyn+OxIAbwKPMfz/rDFdPYvF0BmDC9QxMMzGfkV+JJUjU6at0PPs2mRLg== - dependencies: - pouchdb-binary-utils "7.3.1" - spark-md5 "3.0.2" - -pouchdb-merge@7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/pouchdb-merge/-/pouchdb-merge-7.3.1.tgz#97aae682d7d8499b62b6ce234dcb9527c7bf6f02" - integrity sha512-FeK3r35mKimokf2PQ2tUI523QWyZ4lYZ0Yd75FfSch/SPY6wIokz5XBZZ6PHdu5aOJsEKzoLUxr8CpSg9DhcAw== - -pouchdb-selector-core@7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/pouchdb-selector-core/-/pouchdb-selector-core-7.3.1.tgz#08245662de3d61f16ab8dae2b56ef622935b3fb3" - integrity sha512-HBX+nNGXcaL9z0uNpwSMRq2GNZd3EZXW+fe9rJHS0hvJohjZL7aRJLoaXfEdHPRTNW+CpjM3Rny60eGekQdI/w== - dependencies: - pouchdb-collate "7.3.1" - pouchdb-utils "7.3.1" - -pouchdb-utils@7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/pouchdb-utils/-/pouchdb-utils-7.3.1.tgz#d25f0a034427f388ba5ae37d9ae3fbed210e8720" - integrity sha512-R3hHBo1zTdTu/NFs3iqkcaQAPwhIH0gMIdfVKd5lbDYlmP26rCG5pdS+v7NuoSSFLJ4xxnaGV+Gjf4duYsJ8wQ== - dependencies: - argsarray "0.0.1" - clone-buffer "1.0.0" - immediate "3.3.0" - inherits "2.0.4" - pouchdb-collections "7.3.1" - pouchdb-errors "7.3.1" - pouchdb-md5 "7.3.1" - uuid "8.3.2" - -pouchdb@7.3.0: - version "7.3.0" - resolved "https://registry.yarnpkg.com/pouchdb/-/pouchdb-7.3.0.tgz#440fbef12dfd8f9002320802528665e883a3b7f8" - integrity sha512-OwsIQGXsfx3TrU1pLruj6PGSwFH+h5k4hGNxFkZ76Um7/ZI8F5TzUHFrpldVVIhfXYi2vP31q0q7ot1FSLFYOw== - dependencies: - abort-controller "3.0.0" - argsarray "0.0.1" - buffer-from "1.1.2" - clone-buffer "1.0.0" - double-ended-queue "2.1.0-0" - fetch-cookie "0.11.0" - immediate "3.3.0" - inherits "2.0.4" - level "6.0.1" - level-codec "9.0.2" - level-write-stream "1.0.0" - leveldown "5.6.0" - levelup "4.4.0" - ltgt "2.2.1" - node-fetch "2.6.7" - readable-stream "1.1.14" - spark-md5 "3.0.2" - through2 "3.0.2" - uuid "8.3.2" - vuvuzela "1.0.3" - -prebuild-install@^6.0.0: - version "6.1.4" - resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-6.1.4.tgz#ae3c0142ad611d58570b89af4986088a4937e00f" - integrity sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ== - dependencies: - detect-libc "^1.0.3" - expand-template "^2.0.3" - github-from-package "0.0.0" - minimist "^1.2.3" - mkdirp-classic "^0.5.3" - napi-build-utils "^1.0.1" - node-abi "^2.21.0" - npmlog "^4.0.1" - pump "^3.0.0" - rc "^1.2.7" - simple-get "^3.0.3" - tar-fs "^2.0.0" - tunnel-agent "^0.6.0" + version "3.0.0" + resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-3.0.0.tgz#baf7a8b3ebab19b7f38f07566c7aab0962f0c86a" + integrity sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw== + +postgres-range@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/postgres-range/-/postgres-range-1.1.3.tgz#9ccd7b01ca2789eb3c2e0888b3184225fa859f76" + integrity sha512-VdlZoocy5lCP0c/t66xAfclglEapXPCIVhqqJRncYpvbCgImF0w67aPKfbqUMr72tO2k5q0TdTZwCLjPTI6C9g== prebuild-install@^7.0.1, prebuild-install@^7.1.1: version "7.1.1" @@ -19970,11 +12755,6 @@ prebuild-install@^7.0.1, prebuild-install@^7.1.1: tar-fs "^2.0.0" tunnel-agent "^0.6.0" -precond@0.2: - version "0.2.3" - resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac" - integrity sha512-QCYG84SgGyGzqJ/vlMsxeXd/pgL/I94ixdNFyh1PusWmTCyVfPJjZ1K1jvHtsbfnXQs2TSkEP2fR7QiMZAnKFQ== - preferred-pm@^3.0.0: version "3.1.2" resolved "https://registry.yarnpkg.com/preferred-pm/-/preferred-pm-3.1.2.tgz#aedb70550734a574dffcbf2ce82642bd1753bdd6" @@ -19985,59 +12765,11 @@ preferred-pm@^3.0.0: path-exists "^4.0.0" which-pm "2.0.0" -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== - -prepend-http@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" - integrity sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg== - -prepend-http@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" - integrity sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA== - -preserve@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" - integrity sha512-s/46sYeylUfHNjI+sA/78FAHlmIuKqI9wNnzEOGehAlUUYeObv5C2mOinXBjyUyWmJ2SfcS2/ydApH4hTF4WXQ== - -prettier-plugin-solidity@1.0.0-alpha.35: - version "1.0.0-alpha.35" - resolved "https://registry.yarnpkg.com/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-alpha.35.tgz#922ccad3c6c11c721997a52edbc3d0d8bbcde845" - integrity sha512-zxmCPSA1dECxYZ4JySMzOKocjELB/gvsWsFynYluhwZx6VOHSc3Iu0PesrUkxXd8a7bz31qc9MD7m76VjpsNVA== - dependencies: - dir-to-object "^2.0.0" - emoji-regex "^8.0.0" - escape-string-regexp "^2.0.0" - extract-comments "^1.1.0" - prettier "^1.15.3" - semver "^6.3.0" - solidity-parser-antlr "^0.4.11" - string-width "^4.1.0" - -prettier-plugin-solidity@^1.0.0-dev.23: - version "1.1.3" - resolved "https://registry.yarnpkg.com/prettier-plugin-solidity/-/prettier-plugin-solidity-1.1.3.tgz#9a35124f578404caf617634a8cab80862d726cba" - integrity sha512-fQ9yucPi2sBbA2U2Xjh6m4isUTJ7S7QLc/XDDsktqqxYfTwdYKJ0EnnywXHwCGAaYbQNK+HIYPL1OemxuMsgeg== - dependencies: - "@solidity-parser/parser" "^0.16.0" - semver "^7.3.8" - solidity-comments-extractor "^0.0.7" - -prettier@1.19.1, prettier@^1.14.2, prettier@^1.14.3, prettier@^1.15.3: +prettier@1.19.1: version "1.19.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== -prettier@^2.1.2, prettier@^2.8.1: - version "2.8.8" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" - integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== - prettier@^2.7.1: version "2.8.7" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.7.tgz#bb79fc8729308549d28fe3a98fce73d2c0656450" @@ -20084,12 +12816,7 @@ process@^0.11.1, process@^0.11.10: resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== -progress@^1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" - integrity sha512-UdA8mJ4weIkUBO224tIarHzuHs4HuYiJvsuGT7j/SPQiUJVjYvNDBIPa0hAorduOfjGohB/qHWRa/lrrWX/mXw== - -progress@^2.0.0, progress@^2.0.3: +progress@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== @@ -20117,32 +12844,6 @@ promise-retry@^2.0.1: err-code "^2.0.2" retry "^0.12.0" -promise-to-callback@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/promise-to-callback/-/promise-to-callback-1.0.0.tgz#5d2a749010bfb67d963598fcd3960746a68feef7" - integrity sha512-uhMIZmKM5ZteDMfLgJnoSq9GCwsNKrYau73Awf1jIy6/eUcuuZ3P+CD9zUv0kJsIUbU+x6uLNIhXhLHDs1pNPA== - dependencies: - is-fn "^1.0.0" - set-immediate-shim "^1.0.1" - -promise.allsettled@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/promise.allsettled/-/promise.allsettled-1.0.2.tgz#d66f78fbb600e83e863d893e98b3d4376a9c47c9" - integrity sha512-UpcYW5S1RaNKT6pd+s9jp9K9rlQge1UXKskec0j6Mmuq7UJCvlS2J2/s/yuPN8ehftf9HXMxWlKiPbGGUzpoRg== - dependencies: - array.prototype.map "^1.0.1" - define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" - function-bind "^1.1.1" - iterate-value "^1.0.0" - -promise@^8.0.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/promise/-/promise-8.3.0.tgz#8cb333d1edeb61ef23869fbb8a4ea0279ab60e0a" - integrity sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg== - dependencies: - asap "~2.0.6" - prompt@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/prompt/-/prompt-1.2.0.tgz#5d8f1d9011766bac07abde510dbf4338d87b4f02" @@ -20154,14 +12855,6 @@ prompt@1.2.0: revalidator "0.1.x" winston "2.x" -prompts@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-1.2.0.tgz#598f7722032fb6c399beb24533129d00604c7007" - integrity sha512-g+I6Cer6EefDTawQhGHpdX98nhD7KQrRqyRgKCb+Sc+GG4P64EWRe5DZE402ZNkwrItf97Asf0L1z0g3waOgAA== - dependencies: - kleur "^2.0.1" - sisteransi "^1.0.0" - prompts@^2.0.1: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" @@ -20189,7 +12882,7 @@ proto3-json-serializer@^0.1.8: dependencies: protobufjs "^6.11.2" -protobufjs@6.11.3, protobufjs@^6.11.2, protobufjs@^6.11.3, protobufjs@^6.8.0, protobufjs@^6.8.1, protobufjs@^6.8.6, protobufjs@^6.8.8: +protobufjs@6.11.3, protobufjs@^6.11.2, protobufjs@^6.11.3: version "6.11.3" resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.3.tgz#637a527205a35caa4f3e2a9a4a13ddffe0e7af74" integrity sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg== @@ -20208,16 +12901,6 @@ protobufjs@6.11.3, protobufjs@^6.11.2, protobufjs@^6.11.3, protobufjs@^6.8.0, pr "@types/node" ">=13.7.0" long "^4.0.0" -protobufjs@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-5.0.3.tgz#e4dfe9fb67c90b2630d15868249bcc4961467a17" - integrity sha512-55Kcx1MhPZX0zTbVosMQEO5R6/rikNXd9b6RQK4KSPcrSIIwoXTtebIczUrXlwaSrbz4x8XUVThGPob1n8I4QA== - dependencies: - ascli "~1" - bytebuffer "~5" - glob "^7.0.5" - yargs "^3.10.0" - protobufjs@^7.0.0: version "7.2.3" resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.2.3.tgz#01af019e40d9c6133c49acbb3ff9e30f4f0f70b2" @@ -20272,42 +12955,16 @@ proxy-from-env@^1.1.0: resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== -proxyquire@^2.1.0: - version "2.1.3" - resolved "https://registry.yarnpkg.com/proxyquire/-/proxyquire-2.1.3.tgz#2049a7eefa10a9a953346a18e54aab2b4268df39" - integrity sha512-BQWfCqYM+QINd+yawJz23tbBM40VIGXOdDw3X344KcclI/gtBbdWF6SlQ4nK/bYhF9d27KYug9WzljHC6B9Ysg== - dependencies: - fill-keys "^1.0.2" - module-not-found-error "^1.0.1" - resolve "^1.11.1" - -prr@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" - integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw== - pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== -psl@^1.1.28, psl@^1.1.33: +psl@^1.1.28: version "1.9.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== -public-encrypt@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" - integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== - dependencies: - bn.js "^4.1.0" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - parse-asn1 "^5.0.0" - randombytes "^2.0.1" - safe-buffer "^5.1.2" - pump@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.3.tgz#5dfe8311c33bbf6fc18261f9f34702c47c08a954" @@ -20316,14 +12973,6 @@ pump@^1.0.0: end-of-stream "^1.1.0" once "^1.3.1" -pump@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" - integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - pump@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" @@ -20332,15 +12981,6 @@ pump@^3.0.0: end-of-stream "^1.1.0" once "^1.3.1" -pumpify@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" - integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== - dependencies: - duplexify "^3.6.0" - inherits "^2.0.3" - pump "^2.0.0" - punycode@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" @@ -20420,7 +13060,7 @@ qs@6.11.0: dependencies: side-channel "^1.0.4" -qs@^6.4.0, qs@^6.5.2, qs@^6.7.0: +qs@^6.7.0: version "6.11.1" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.1.tgz#6c29dff97f0c0060765911ba65cbc9764186109f" integrity sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ== @@ -20446,16 +13086,11 @@ querystring@0.2.0: resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g== -querystring@^0.2.0, querystring@^0.2.1: +querystring@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.1.tgz#40d77615bb09d16902a85c3e38aa8b5ed761c2dd" integrity sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg== -querystringify@^2.0.0, querystringify@^2.1.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" - integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== - queue-microtask@^1.2.2, queue-microtask@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -20471,35 +13106,13 @@ quick-lru@^5.1.1: resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== -randomatic@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed" - integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw== - dependencies: - is-number "^4.0.0" - kind-of "^6.0.0" - math-random "^1.0.1" - -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.0.6, randombytes@^2.1.0: +randombytes@^2.0.1, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== dependencies: safe-buffer "^5.1.0" -randomfill@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" - integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== - dependencies: - randombytes "^2.0.5" - safe-buffer "^5.1.0" - -randomhex@0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/randomhex/-/randomhex-0.1.5.tgz#baceef982329091400f2a2912c6cd02f1094f585" - integrity sha512-2+Kkw7UiZGQWOz7rw8hPW44utkBYMEciQfziaZ71RcyDu+refQWzS/0DgfUSa5MwclrOD3sf3vI5vmrTYjwpjQ== - range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" @@ -20525,7 +13138,7 @@ raw-body@2.5.2: iconv-lite "0.4.24" unpipe "1.0.0" -rc@^1.1.2, rc@^1.2.7: +rc@^1.2.7: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== @@ -20545,13 +13158,6 @@ read-cmd-shim@^3.0.0: resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-3.0.1.tgz#868c235ec59d1de2db69e11aec885bc095aea087" integrity sha512-kEmDUoYf/CDy8yZbLTmhB1X9kkjf9Q80PCNsDMb7ufrGd6zZSQA1+UyjrO+pZm5K/S4OXCWJeiIt1JA8kAsa6g== -read-last-lines@^1.7.2: - version "1.8.0" - resolved "https://registry.yarnpkg.com/read-last-lines/-/read-last-lines-1.8.0.tgz#4f94d4345ece7b8083ebb71c5fcdf60bd7afb9cc" - integrity sha512-oPL0cnZkhsO2xF7DBrdzVhXSNajPP5TzzCim/2IAjeGb17ArLLTRriI/ceV6Rook3L27mvbrOvLlf9xYYnaftQ== - dependencies: - mz "^2.7.0" - read-package-json-fast@^2.0.2, read-package-json-fast@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz#323ca529630da82cb34b36cc0b996693c98c2b83" @@ -20640,17 +13246,7 @@ read@1, read@1.0.x, read@^1.0.7: dependencies: mute-stream "~0.0.4" -readable-stream@1.1.14, readable-stream@^1.0.33: - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - integrity sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -"readable-stream@2 || 3", readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.2, readable-stream@^3.1.0, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0, readable-stream@^3.6.2: +readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.2, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== @@ -20659,7 +13255,7 @@ readable-stream@1.1.14, readable-stream@^1.0.33: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readable-stream@^2.0.0, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: +readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@~2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== @@ -20672,21 +13268,6 @@ readable-stream@^2.0.0, readable-stream@^2.0.6, readable-stream@^2.2.2, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@~0.0.2: - version "0.0.4" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-0.0.4.tgz#f32d76e3fb863344a548d79923007173665b3b8d" - integrity sha512-azrivNydKRYt7zwLV5wWUK7YzKTWs3q87xSmY6DlHapPrCvaT6ZrukvM5erV+yCSSPmZT8zkSdttOHQpWWm9zw== - -readable-stream@~1.0.15: - version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - integrity sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - readdir-scoped-modules@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz#8d45407b4f870a0dcaebc0e28670d18e74514309" @@ -20697,27 +13278,6 @@ readdir-scoped-modules@^1.1.0: graceful-fs "^4.1.2" once "^1.3.0" -readdirp@~3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.2.0.tgz#c30c33352b12c96dfb4b895421a49fd5a9593839" - integrity sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ== - dependencies: - picomatch "^2.0.4" - -readdirp@~3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.3.0.tgz#984458d13a1e42e2e9f5841b129e162f369aff17" - integrity sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ== - dependencies: - picomatch "^2.0.7" - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - rechoir@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" @@ -20740,30 +13300,6 @@ redeyed@~2.1.0: dependencies: esprima "~4.0.0" -redux-saga@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/redux-saga/-/redux-saga-1.0.0.tgz#acb8b3ed9180fecbe75f342011d75af3ac11045b" - integrity sha512-GvJWs/SzMvEQgeaw6sRMXnS2FghlvEGsHiEtTLpJqc/FHF3I5EE/B+Hq5lyHZ8LSoT2r/X/46uWvkdCnK9WgHA== - dependencies: - "@redux-saga/core" "^1.0.0" - -redux@^3.7.2: - version "3.7.2" - resolved "https://registry.yarnpkg.com/redux/-/redux-3.7.2.tgz#06b73123215901d25d065be342eb026bc1c8537b" - integrity sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A== - dependencies: - lodash "^4.2.1" - lodash-es "^4.2.1" - loose-envify "^1.1.0" - symbol-observable "^1.0.3" - -redux@^4.0.4: - version "4.2.1" - resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197" - integrity sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w== - dependencies: - "@babel/runtime" "^7.9.2" - regenerator-runtime@^0.11.0: version "0.11.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" @@ -20779,13 +13315,6 @@ regenerator-runtime@^0.14.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz#5e19d68eb12d486f797e15a3c6a918f7cec5eb45" integrity sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA== -regex-cache@^0.4.2: - version "0.4.4" - resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" - integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== - dependencies: - is-equal-shallow "^0.1.3" - regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" @@ -20794,15 +13323,6 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.4.3: - version "1.5.0" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz#fe7ce25e7e4cca8db37b6634c8a2c7009199b9cb" - integrity sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - functions-have-names "^1.2.3" - regexp.prototype.flags@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz#90ce989138db209f81492edd734183ce99f9677e" @@ -20812,33 +13332,6 @@ regexp.prototype.flags@^1.5.1: define-properties "^1.2.0" set-function-name "^2.0.0" -regexpp@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" - integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== - -relative@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/relative/-/relative-3.0.2.tgz#0dcd8ec54a5d35a3c15e104503d65375b5a5367f" - integrity sha512-Q5W2qeYtY9GbiR8z1yHNZ1DGhyjb4AnLEjt8iE6XfcC1QIu+FAtj3HQaO0wH28H1mX6cqNLvAqWhP402dxJGyA== - dependencies: - isobject "^2.0.0" - -remix-lib@>=0.4.1: - version "0.4.30" - resolved "https://registry.yarnpkg.com/remix-lib/-/remix-lib-0.4.30.tgz#2132c6f116afee7b427e4a18d98a30e608d4e015" - integrity sha512-FqJzWF1eKJDZIxiO2LmmTGo7cyQSO+Iq8NDnm/TJcRYR/1a5UKKHSgIZ6rzevA3igMC/RrEhovbE3A/9l7pVzw== - dependencies: - async "^2.1.2" - ethereumjs-block "^2.2.2" - ethereumjs-tx "^2.1.2" - ethereumjs-util "^6.2.0" - ethereumjs-vm "4.1.3" - ethers "^4.0.40" - events "^3.0.0" - solc "^0.6.0" - web3 "^1.2.4" - remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" @@ -20849,52 +13342,12 @@ repeat-element@^1.1.2: resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== -repeat-string@^1.5.2, repeat-string@^1.6.1: +repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== -req-cwd@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/req-cwd/-/req-cwd-2.0.0.tgz#d4082b4d44598036640fb73ddea01ed53db49ebc" - integrity sha512-ueoIoLo1OfB6b05COxAA9UpeoscNpYyM+BqYlA7H6LVF4hKGPXQQSSaD2YmvDVJMkk4UDpAHIeU1zG53IqjvlQ== - dependencies: - req-from "^2.0.0" - -req-from@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/req-from/-/req-from-2.0.0.tgz#d74188e47f93796f4aa71df6ee35ae689f3e0e70" - integrity sha512-LzTfEVDVQHBRfjOUMgNBA+V6DWsSnoeKzf42J7l0xa/B4jyPOuuF5MlNSmomLNGemWTnV2TIdjSSLnEn95fOQA== - dependencies: - resolve-from "^3.0.0" - -request-promise-core@1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f" - integrity sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw== - dependencies: - lodash "^4.17.19" - -request-promise-native@^1.0.5: - version "1.0.9" - resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28" - integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g== - dependencies: - request-promise-core "1.1.4" - stealthy-require "^1.1.1" - tough-cookie "^2.3.3" - -request-promise@^4.2.2: - version "4.2.6" - resolved "https://registry.yarnpkg.com/request-promise/-/request-promise-4.2.6.tgz#7e7e5b9578630e6f598e3813c0f8eb342a27f0a2" - integrity sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ== - dependencies: - bluebird "^3.5.0" - request-promise-core "1.1.4" - stealthy-require "^1.1.1" - tough-cookie "^2.3.3" - -request@^2.67.0, request@^2.79.0, request@^2.85.0, request@^2.88.0: +request@^2.79.0: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -20930,7 +13383,7 @@ require-from-string@^1.1.0: resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418" integrity sha512-H7AkJWMobeskkttHyhTVtS0fxpFLjxhbfMa6Bk3wimP7sdPRGL3EyCg3sAQenFfAe+xQ+oAc85Nmtvq0ROM83Q== -require-from-string@^2.0.0, require-from-string@^2.0.1, require-from-string@^2.0.2: +require-from-string@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== @@ -20954,25 +13407,6 @@ require-main-filename@^2.0.0: resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== - -reselect-tree@^1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/reselect-tree/-/reselect-tree-1.3.7.tgz#c3eca58765d9df96bae0017f6ff3504c304cdea0" - integrity sha512-kZN+C1cVJ6fFN2smSb0l4UvYZlRzttgnu183svH4NrU22cBY++ikgr2QT75Uuk4MYpv5gXSVijw4c5U6cx6GKg== - dependencies: - debug "^3.1.0" - json-pointer "^0.6.1" - reselect "^4.0.0" - -reselect@^4.0.0: - version "4.1.8" - resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.8.tgz#3f5dc671ea168dccdeb3e141236f69f02eaec524" - integrity sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ== - resolve-alpn@^1.0.0, resolve-alpn@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" @@ -20985,27 +13419,6 @@ resolve-cwd@^3.0.0: dependencies: resolve-from "^5.0.0" -resolve-dir@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-0.1.1.tgz#b219259a5602fac5c5c496ad894a6e8cc430261e" - integrity sha512-QxMPqI6le2u0dCLyiGzgy92kjkkL6zO0XyvHzjdTNH3zM6e5Hz3BwG6+aEyNgiQ5Xz6PwTwgQEj3U50dByPKIA== - dependencies: - expand-tilde "^1.2.2" - global-modules "^0.2.3" - -resolve-dir@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" - integrity sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg== - dependencies: - expand-tilde "^2.0.0" - global-modules "^1.0.0" - -resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - integrity sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw== - resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -21026,12 +13439,7 @@ resolve.exports@^2.0.0: resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== -resolve@1.1.x: - version "1.1.7" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" - integrity sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg== - -resolve@^1.1.6, resolve@^1.10.0, resolve@^1.11.1, resolve@^1.14.2, resolve@^1.20.0, resolve@^1.3.2, resolve@^1.8.1, resolve@~1.22.1: +resolve@^1.1.6, resolve@^1.10.0, resolve@^1.20.0, resolve@^1.3.2: version "1.22.2" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== @@ -21049,13 +13457,6 @@ resolve@^1.22.1: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -responselike@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" - integrity sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ== - dependencies: - lowercase-keys "^1.0.0" - responselike@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.1.tgz#9a0bc8fdc252f3fb1cca68b016591059ba1422bc" @@ -21063,14 +13464,6 @@ responselike@^2.0.0: dependencies: lowercase-keys "^2.0.0" -restore-cursor@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" - integrity sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q== - dependencies: - onetime "^2.0.0" - signal-exit "^3.0.2" - restore-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" @@ -21079,21 +13472,6 @@ restore-cursor@^3.1.0: onetime "^5.1.0" signal-exit "^3.0.2" -restore-cursor@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-4.0.0.tgz#519560a4318975096def6e609d44100edaa4ccb9" - integrity sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg== - dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" - -resumer@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" - integrity sha512-Fn9X8rX8yYF4m81rZCK/5VmrmsSbqS/i3rDLl6ZZHAXgC2nTAx3dhwG8q8odP/RmdLa2YrybDJaAMg+X1ajY3w== - dependencies: - through "~2.3.4" - ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" @@ -21107,11 +13485,6 @@ retry-request@^4.0.0: debug "^4.1.1" extend "^3.0.2" -retry@0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" - integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== - retry@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" @@ -21127,13 +13500,6 @@ revalidator@0.1.x: resolved "https://registry.yarnpkg.com/revalidator/-/revalidator-0.1.8.tgz#fece61bfa0c1b52a206bd6b18198184bdd523a3b" integrity sha512-xcBILK2pA9oh4SiinPEZfhP8HfrB/ha+a2fTMyl7Om2WjlDVrOQy99N2MXXlUHqGJz4qEu2duXxHJjDWuK/0xg== -rimraf@2.6.3: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" @@ -21141,20 +13507,13 @@ rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2: dependencies: glob "^7.1.3" -rimraf@^2.2.8, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3: +rimraf@^2.2.8, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== dependencies: glob "^7.1.3" -rimraf@^5.0.5: - version "5.0.5" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.5.tgz#9be65d2d6e683447d2e9013da2bf451139a61ccf" - integrity sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A== - dependencies: - glob "^10.3.7" - rimraf@~2.4.0: version "2.4.5" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.4.5.tgz#ee710ce5d93a8fdb856fb5ea8ff0e2d75934b2da" @@ -21175,25 +13534,18 @@ ripemd160@^2.0.0, ripemd160@^2.0.1, ripemd160@^2.0.2: hash-base "^3.0.0" inherits "^2.0.1" -rlp@^2.0.0, rlp@^2.2.1, rlp@^2.2.2, rlp@^2.2.3, rlp@^2.2.4: +rlp@^2.2.4: version "2.2.7" resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== dependencies: bn.js "^5.2.0" -run-async@^2.2.0, run-async@^2.4.0: +run-async@^2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== -run-parallel-limit@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz#be80e936f5768623a38a963262d6bef8ff11e7ba" - integrity sha512-jJA7irRNM91jaKc3Hcl1npHsFLOXOoTkPCUL1JEa1R82O2miplXXRaGdjW/KM/98YQWDhJLiSs793CnXfblJUw== - dependencies: - queue-microtask "^1.2.2" - run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -21201,11 +13553,6 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -rustbn.js@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" - integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== - rxjs@6, rxjs@^6.4.0, rxjs@^6.6.0: version "6.6.7" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" @@ -21220,16 +13567,6 @@ rxjs@^7.5.5: dependencies: tslib "^2.1.0" -safe-array-concat@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.0.tgz#2064223cba3c08d2ee05148eedbc563cd6d84060" - integrity sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.2.0" - has-symbols "^1.0.3" - isarray "^2.0.5" - safe-array-concat@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.1.tgz#91686a63ce3adbea14d61b14c99572a8ff84754c" @@ -21250,13 +13587,6 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-event-emitter@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/safe-event-emitter/-/safe-event-emitter-1.0.1.tgz#5b692ef22329ed8f69fdce607e50ca734f6f20af" - integrity sha512-e1wFe99A91XYYxoQbcq2ZJUWurxEyP8vfz7A7vuUe1s95q8r5ebraVaA1BukYJcpM6V16ugWoD9vngi8Ccu5fg== - dependencies: - events "^3.0.0" - safe-json-stringify@~1: version "1.2.0" resolved "https://registry.yarnpkg.com/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz#356e44bc98f1f93ce45df14bcd7c01cda86e0afd" @@ -21288,16 +13618,11 @@ sax@1.2.1: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" integrity sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA== -sax@>=0.6.0, sax@^1.2.4: +sax@>=0.6.0: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== -scrypt-js@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.3.tgz#bb0040be03043da9a012a2cea9fc9f852cfc87d4" - integrity sha512-d8DzQxNivoNDogyYmb/9RD5mEQE/Q7vG2dLDUgvfPmKL9xCVzgqUntOdS0me9Cq9Sh9VxIZuoNEFcsfyXRnyUw== - scrypt-js@2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.4.tgz#32f8c5149f0797672e551c07e230f834b6af5f16" @@ -21308,25 +13633,6 @@ scrypt-js@3.0.1, scrypt-js@^3.0.0, scrypt-js@^3.0.1: resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== -"scrypt-shim@github:web3-js/scrypt-shim": - version "0.1.0" - resolved "https://codeload.github.com/web3-js/scrypt-shim/tar.gz/aafdadda13e660e25e1c525d1f5b2443f5eb1ebb" - dependencies: - scryptsy "^2.1.0" - semver "^6.3.0" - -scryptsy@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163" - integrity sha512-aldIRgMozSJ/Gl6K6qmJZysRP82lz83Wb42vl4PWN8SaLFHIaOzLPc9nUUW2jQN88CuGm5q5HefJ9jZ3nWSmTw== - dependencies: - pbkdf2 "^3.0.3" - -scryptsy@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-2.1.0.tgz#8d1e8d0c025b58fdd25b6fa9a0dc905ee8faa790" - integrity sha512-1CdSqHQowJBnMAFyPEBRfqag/YP9OF394FV+4YREIJX4ljD7OxvQRDayyoyyCk+senRjSkP6VnUNQmVQqB6g7w== - secp256k1@4.0.3, secp256k1@^4.0.0, secp256k1@^4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" @@ -21336,62 +13642,11 @@ secp256k1@4.0.3, secp256k1@^4.0.0, secp256k1@^4.0.1: node-addon-api "^2.0.0" node-gyp-build "^4.2.0" -secp256k1@^3.0.1: - version "3.8.0" - resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.8.0.tgz#28f59f4b01dbee9575f56a47034b7d2e3b3b352d" - integrity sha512-k5ke5avRZbtl9Tqx/SA7CbY3NF6Ro+Sj9cZxezFzuBlLDmyqPiL8hJJ+EmzD8Ig4LUDByHJ3/iPOVoRixs/hmw== - dependencies: - bindings "^1.5.0" - bip66 "^1.1.5" - bn.js "^4.11.8" - create-hash "^1.2.0" - drbg.js "^1.0.1" - elliptic "^6.5.2" - nan "^2.14.0" - safe-buffer "^5.1.2" - -seed-random@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/seed-random/-/seed-random-2.2.0.tgz#2a9b19e250a817099231a5b99a4daf80b7fbed54" - integrity sha512-34EQV6AAHQGhoc0tn/96a9Fsi6v2xdqe/dMUwljGRaFOzR3EgRmECvD0O8vi8X+/uQ50LGHfkNu/Eue5TPKZkQ== - -seedrandom@3.0.5: - version "3.0.5" - resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.5.tgz#54edc85c95222525b0c7a6f6b3543d8e0b3aa0a7" - integrity sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg== - -seek-bzip@^1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.6.tgz#35c4171f55a680916b52a07859ecf3b5857f21c4" - integrity sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ== - dependencies: - commander "^2.8.1" - -semaphore-async-await@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/semaphore-async-await/-/semaphore-async-await-1.5.1.tgz#857bef5e3644601ca4b9570b87e9df5ca12974fa" - integrity sha512-b/ptP11hETwYWpeilHXXQiV5UJNJl7ZWWooKRE5eBIYWoom6dZ0SluCIdCtKycsMtZgKWE01/qAw6jblw1YVhg== - -semaphore@>=1.0.1, semaphore@^1.0.3, semaphore@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa" - integrity sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA== - -"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0: +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0, semver@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" - integrity sha512-VyFUffiBx8hABJ9HYSTXLRwyZtdDHMzMtFmID1aiNAD2BZppBmJm0Hqw3p2jkgxP9BNt1pQ9RnC49P0EcXf6cA== - -semver@5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" - integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== - semver@7.3.4: version "7.3.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" @@ -21406,21 +13661,14 @@ semver@7.3.5: dependencies: lru-cache "^6.0.0" -semver@7.3.7: - version "7.3.7" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" - integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== - dependencies: - lru-cache "^6.0.0" - -semver@7.x, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.4.0: +semver@7.x, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.4.0: version "7.5.0" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.0.tgz#ed8c5dc8efb6c629c88b23d41dc9bf40c1d96cd0" integrity sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA== dependencies: lru-cache "^6.0.0" -semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: +semver@^6.0.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -21432,11 +13680,6 @@ semver@^7.5.2, semver@^7.5.3, semver@^7.5.4: dependencies: lru-cache "^6.0.0" -semver@~5.4.1: - version "5.4.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" - integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== - send@0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" @@ -21464,27 +13707,6 @@ sentence-case@^2.1.0: no-case "^2.2.0" upper-case-first "^1.1.2" -sentence-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/sentence-case/-/sentence-case-3.0.4.tgz#3645a7b8c117c787fde8702056225bb62a45131f" - integrity sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg== - dependencies: - no-case "^3.0.4" - tslib "^2.0.3" - upper-case-first "^2.0.2" - -serialize-javascript@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-3.0.0.tgz#492e489a2d77b7b804ad391a5f5d97870952548e" - integrity sha512-skZcHYw2vEX4bw90nAr2iTTsz6x2SrHEnfxgKYmZlvJYBEZrvbKtobJWlQ20zczKb3bsHHXXTYt48zBA7ni9cw== - -serialize-javascript@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" - integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== - dependencies: - randombytes "^2.1.0" - serve-static@1.15.0: version "1.15.0" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" @@ -21506,7 +13728,7 @@ servify@^0.1.12: request "^2.79.0" xhr "^2.3.3" -set-blocking@^2.0.0, set-blocking@~2.0.0: +set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== @@ -21530,19 +13752,6 @@ set-function-name@^2.0.0: functions-have-names "^1.2.3" has-property-descriptors "^1.0.0" -set-immediate-shim@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" - integrity sha512-Li5AOqrZWCVA2n5kryzEmqai6bKSIvpz5oUJHPVj6+dsbD3X1ixtsY5tEnsaNpH3pFAHmG8eIHUrtEtohrg+UQ== - -set-value@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.2.0.tgz#73b0a6825c158c6a16a82bbdc95775bf2a825fab" - integrity sha512-dJaeu7V8d1KwjePimg1oOpGp31cEw/uRcZlfL7wwemkr+A00ev/ZhikvSMiQ4hkf83d8JdY2AFoFmXsKzmHMSw== - dependencies: - isobject "^1.0.0" - noncharacters "^1.1.0" - set-value@^2.0.0, set-value@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" @@ -21568,7 +13777,7 @@ setprototypeof@1.2.0: resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== -sha.js@^2.4.0, sha.js@^2.4.11, sha.js@^2.4.8: +sha.js@^2.4.0, sha.js@^2.4.8: version "2.4.11" resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== @@ -21576,14 +13785,6 @@ sha.js@^2.4.0, sha.js@^2.4.11, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" -sha1@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/sha1/-/sha1-1.1.1.tgz#addaa7a93168f393f19eb2b15091618e2700f848" - integrity sha512-dZBS6OrMjtgVkopB1Gmo4RQCDKiZsqcpAQpkV/aaj+FCrCg8r4I4qMkDPQjBgLIxlmu9k4nUbWq6ohXahOneYA== - dependencies: - charenc ">= 0.0.1" - crypt ">= 0.0.1" - sha3@^2.1.1: version "2.1.4" resolved "https://registry.yarnpkg.com/sha3/-/sha3-2.1.4.tgz#000fac0fe7c2feac1f48a25e7a31b52a6492cc8f" @@ -21598,11 +13799,6 @@ shallow-clone@^3.0.0: dependencies: kind-of "^6.0.2" -shallowequal@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" - integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ== - shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" @@ -21655,11 +13851,6 @@ signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== -signal-exit@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" - integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== - simple-concat@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" @@ -21674,15 +13865,6 @@ simple-get@^2.7.0: once "^1.3.1" simple-concat "^1.0.0" -simple-get@^3.0.3: - version "3.1.1" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.1.tgz#cc7ba77cfbe761036fbfce3d021af25fc5584d55" - integrity sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA== - dependencies: - decompress-response "^4.2.0" - once "^1.3.1" - simple-concat "^1.0.0" - simple-get@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.1.tgz#4a39db549287c979d352112fa03fd99fd6bc3543" @@ -21692,7 +13874,7 @@ simple-get@^4.0.0: once "^1.3.1" simple-concat "^1.0.0" -sisteransi@^1.0.0, sisteransi@^1.0.5: +sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== @@ -21702,42 +13884,11 @@ slash@^1.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" integrity sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg== -slash@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" - integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== - slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -slash@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" - integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== - -sleep-promise@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/sleep-promise/-/sleep-promise-8.0.1.tgz#8d795a27ea23953df6b52b91081e5e22665993c5" - integrity sha512-nfwyX+G1dsx2R1DMMKWLpNxuHMOCL7JIRBUw0fl7Z4nZ1YZK0apZuGY8MDexn0HDZzgbERgj/CrNtsYpo/B7eA== - -sleep@6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/sleep/-/sleep-6.1.0.tgz#5507b520556a82ffb983d39123c5459470fa2a9e" - integrity sha512-Z1x4JjJxsru75Tqn8F4tnOFeEu3HjtITTsumYUiuz54sGKdISgLCek9AUlXlVVrkhltRFhNUsJDJE76SFHTDIQ== - dependencies: - nan "^2.13.2" - -slice-ansi@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== - dependencies: - ansi-styles "^3.2.0" - astral-regex "^1.0.0" - is-fullwidth-code-point "^2.0.0" - smart-buffer@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" @@ -21762,19 +13913,6 @@ snake-case@^2.1.0: dependencies: no-case "^2.2.0" -snake-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c" - integrity sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg== - dependencies: - dot-case "^3.0.4" - tslib "^2.0.3" - -snakeize@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/snakeize/-/snakeize-0.1.0.tgz#10c088d8b58eb076b3229bb5a04e232ce126422d" - integrity sha512-ot3bb6pQt6IVq5G/JQ640ceSYTPtriVrwNyfoUw1LmQQGzPMAGxE5F+ded2UwSUCyf2PW1fFAYUnVEX21PWbpQ== - snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" @@ -21836,33 +13974,7 @@ solc@0.5.8: tmp "0.0.33" yargs "^11.0.0" -solc@0.8.19, solc@^0.8: - version "0.8.19" - resolved "https://registry.yarnpkg.com/solc/-/solc-0.8.19.tgz#cac6541106ae3cff101c740042c7742aa56a2ed3" - integrity sha512-yqurS3wzC4LdEvmMobODXqprV4MYJcVtinuxgrp61ac8K2zz40vXA0eSAskSHPgv8dQo7Nux39i3QBsHx4pqyA== - dependencies: - command-exists "^1.2.8" - commander "^8.1.0" - follow-redirects "^1.12.1" - js-sha3 "0.8.0" - memorystream "^0.3.1" - semver "^5.5.0" - tmp "0.0.33" - -solc@0.8.21: - version "0.8.21" - resolved "https://registry.yarnpkg.com/solc/-/solc-0.8.21.tgz#c3cd505c360ea2fa0eaa5ab574ef96bffb1a2766" - integrity sha512-N55ogy2dkTRwiONbj4e6wMZqUNaLZkiRcjGyeafjLYzo/tf/IvhHY5P5wpe+H3Fubh9idu071i8eOGO31s1ylg== - dependencies: - command-exists "^1.2.8" - commander "^8.1.0" - follow-redirects "^1.12.1" - js-sha3 "0.8.0" - memorystream "^0.3.1" - semver "^5.5.0" - tmp "0.0.33" - -solc@^0.4.2, solc@^0.4.20: +solc@^0.4.20: version "0.4.26" resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.26.tgz#5390a62a99f40806b86258c737c1cf653cc35cb5" integrity sha512-o+c6FpkiHd+HPjmjEVpQgH7fqZ14tJpXhho+/bQXlXbliLIS/xjXb42Vxh+qQY1WCSTMQ0+a5vR9vi0MfhU6mA== @@ -21873,71 +13985,6 @@ solc@^0.4.2, solc@^0.4.20: semver "^5.3.0" yargs "^4.7.1" -solc@^0.5.8: - version "0.5.17" - resolved "https://registry.yarnpkg.com/solc/-/solc-0.5.17.tgz#8a76c50e98d49ca7610cca2fdc78ff3016540c67" - integrity sha512-qpX+PGaU0Q3c6lh2vDzMoIbhv6bIrecI4bYsx+xUs01xsGFnY6Nr0L8y/QMyutTnrHN6Lb/Yl672ZVRqxka96w== - dependencies: - command-exists "^1.2.8" - commander "3.0.2" - fs-extra "^0.30.0" - js-sha3 "0.8.0" - memorystream "^0.3.1" - require-from-string "^2.0.0" - semver "^5.5.0" - tmp "0.0.33" - -solc@^0.6.0: - version "0.6.12" - resolved "https://registry.yarnpkg.com/solc/-/solc-0.6.12.tgz#48ac854e0c729361b22a7483645077f58cba080e" - integrity sha512-Lm0Ql2G9Qc7yPP2Ba+WNmzw2jwsrd3u4PobHYlSOxaut3TtUbj9+5ZrT6f4DUpNPEoBaFUOEg9Op9C0mk7ge9g== - dependencies: - command-exists "^1.2.8" - commander "3.0.2" - fs-extra "^0.30.0" - js-sha3 "0.8.0" - memorystream "^0.3.1" - require-from-string "^2.0.0" - semver "^5.5.0" - tmp "0.0.33" - -solhint@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/solhint/-/solhint-2.3.1.tgz#6fee8fc2635112bf5812f7cba8359c14e9d9a491" - integrity sha512-wP/G+Dqj8LNWlCI9Mt6XiQRWQfZwv1rkZe/V+HKtip5SAZJVvp144PdH28KE45ZvR99Hhrp/Mujt74fSmXsFiw== - dependencies: - ajv "^6.6.1" - antlr4 "4.7.1" - chalk "^2.4.2" - commander "2.18.0" - cosmiconfig "^5.0.7" - eslint "^5.6.0" - fast-diff "^1.1.2" - glob "^7.1.3" - ignore "^4.0.6" - js-yaml "^3.12.0" - lodash "^4.17.11" - semver "^6.3.0" - optionalDependencies: - prettier "^1.14.3" - -solidity-bytes-utils@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/solidity-bytes-utils/-/solidity-bytes-utils-0.0.7.tgz#ccc865a6694b4865f2020cee37c15cc26f81cf9b" - integrity sha512-NdzNDmzpd45MiEmYS5MVW1O0ovjneyXpPV5iWt05juA77KFQqO2axQOdkMGvKtA69nxobKQU9BakopeT48bWRQ== - dependencies: - truffle-hdwallet-provider "0.0.3" - -solidity-comments-extractor@^0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz#99d8f1361438f84019795d928b931f4e5c39ca19" - integrity sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw== - -solidity-parser-antlr@^0.4.11, solidity-parser-antlr@^0.4.2: - version "0.4.11" - resolved "https://registry.yarnpkg.com/solidity-parser-antlr/-/solidity-parser-antlr-0.4.11.tgz#af43e1f13b3b88309a875455f5d6e565b05ee5f1" - integrity sha512-4jtxasNGmyC0midtjH/lTFPZYvTTUMy6agYcF+HoMnzW8+cqo3piFrINb4ZCzpPW+7tTVFCGa5ubP34zOzeuMg== - sort-keys@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128" @@ -21971,14 +14018,6 @@ source-map-support@0.5.13: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-support@^0.5.0, source-map-support@^0.5.16, source-map-support@^0.5.17, source-map-support@^0.5.19: - version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - source-map-url@^0.4.0: version "0.4.1" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" @@ -21994,18 +14033,6 @@ source-map@^0.6.0, source-map@^0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -source-map@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" - integrity sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA== - dependencies: - amdefine ">=0.0.4" - -spark-md5@3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/spark-md5/-/spark-md5-3.0.2.tgz#7952c4a30784347abcee73268e473b9c0167e3fc" - integrity sha512-wcFzz9cDfbuqe0FZzfi2or1sgyIrsDwmPwfZC4hiNidPdPINjeUwNfv5kldczoEAcjl9Y1L3SM7Uz2PUEQzxQw== - spawndamnit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/spawndamnit/-/spawndamnit-2.0.0.tgz#9f762ac5c3476abb994b42ad592b5ad22bb4b0ad" @@ -22040,22 +14067,6 @@ spdx-license-ids@^3.0.0: resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz#7189a474c46f8d47c7b0da4b987bb45e908bd2d5" integrity sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w== -spinnies@^0.4.2: - version "0.4.3" - resolved "https://registry.yarnpkg.com/spinnies/-/spinnies-0.4.3.tgz#2ea0ad148e78353ddf621dec3951a6f4c3cbf66e" - integrity sha512-TTA2vWXrXJpfThWAl2t2hchBnCMI1JM5Wmb2uyI7Zkefdw/xO98LDy6/SBYwQPiYXL3swx3Eb44ZxgoS8X5wpA== - dependencies: - chalk "^2.4.2" - cli-cursor "^3.0.0" - strip-ansi "^5.2.0" - -split-array-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/split-array-stream/-/split-array-stream-2.0.0.tgz#85a4f8bfe14421d7bca7f33a6d176d0c076a53b1" - integrity sha512-hmMswlVY91WvGMxs0k8MRgq8zb2mSen4FmDNc5AFiTWtrBpdZN6nwD6kROVe4vNL+ywrvbCKsWVCnEd4riELIg== - dependencies: - is-stream-ended "^0.1.4" - split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" @@ -22070,11 +14081,6 @@ split2@^3.0.0: dependencies: readable-stream "^3.0.0" -split2@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" - integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== - split@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" @@ -22121,11 +14127,6 @@ stack-utils@^2.0.3: dependencies: escape-string-regexp "^2.0.0" -starts-with@^1.0.0, starts-with@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/starts-with/-/starts-with-1.0.2.tgz#16793a729d89d4cf3d4fb2eda2f908ae357f196f" - integrity sha512-QUw5X+IMTGDm1nrdowEdDaA0MNiUmRlQFwpTTXmhuPKQc+7b0h8fOHtlt1zZqcEK5x1Fsitrobo7KEusc+d1rg== - static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" @@ -22139,36 +14140,12 @@ statuses@2.0.1: resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== -"statuses@>= 1.5.0 < 2": - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== - -stdin-discarder@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/stdin-discarder/-/stdin-discarder-0.1.0.tgz#22b3e400393a8e28ebf53f9958f3880622efde21" - integrity sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ== - dependencies: - bl "^5.0.0" - -stealthy-require@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" - integrity sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g== - -stop-iteration-iterator@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz#6a60be0b4ee757d1ed5254858ec66b10c49285e4" - integrity sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ== - dependencies: - internal-slot "^1.0.4" - stoppable@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/stoppable/-/stoppable-1.1.0.tgz#32da568e83ea488b08e4d7ea2c3bcc9d75015d5b" integrity sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw== -stream-events@^1.0.1, stream-events@^1.0.4, stream-events@^1.0.5: +stream-events@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/stream-events/-/stream-events-1.0.5.tgz#bbc898ec4df33a4902d892333d47da9bf1c406d5" integrity sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg== @@ -22192,11 +14169,6 @@ strict-uri-encode@^1.0.0: resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" integrity sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ== -string-hash@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b" - integrity sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A== - string-length@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" @@ -22210,15 +14182,6 @@ string-template@~0.2.1: resolved "https://registry.yarnpkg.com/string-template/-/string-template-0.2.1.tgz#42932e598a352d01fc22ec3367d9d84eec6c9add" integrity sha512-Yptehjogou2xm4UJbxJ4CxgZx12HBfeystp0y3x7s4Dj32ltVVG1Gg8YhKjHZkHicuKpZX/ffilA8505VbUbpw== -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - 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" - string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -22228,7 +14191,16 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + 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" + +string-width@^2.0.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -22245,24 +14217,6 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string-width@^5.0.1, string-width@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" - integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== - dependencies: - eastasianwidth "^0.2.0" - emoji-regex "^9.2.2" - strip-ansi "^7.0.1" - -string.prototype.trim@^1.2.7, string.prototype.trim@~1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533" - integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - string.prototype.trim@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz#f9ac6f8af4bd55ddfa8895e6aea92a96395393bd" @@ -22272,15 +14226,6 @@ string.prototype.trim@^1.2.8: define-properties "^1.2.0" es-abstract "^1.22.1" -string.prototype.trimend@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" - integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - string.prototype.trimend@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz#1bb3afc5008661d73e2dc015cd4853732d6c471e" @@ -22290,15 +14235,6 @@ string.prototype.trimend@^1.0.7: define-properties "^1.2.0" es-abstract "^1.22.1" -string.prototype.trimstart@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" - integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - string.prototype.trimstart@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz#d4cdb44b83a4737ffbac2d406e405d43d0184298" @@ -22315,11 +14251,6 @@ string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== - string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" @@ -22327,13 +14258,6 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" @@ -22355,12 +14279,12 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" -strip-ansi@^7.0.1: - version "7.1.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" - integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: - ansi-regex "^6.0.1" + ansi-regex "^5.0.1" strip-bom@^2.0.0: version "2.0.0" @@ -22379,18 +14303,6 @@ strip-bom@^4.0.0: resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== -strip-comments@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-comments/-/strip-comments-2.0.1.tgz#4ad11c3fbcac177a67a40ac224ca339ca1c1ba9b" - integrity sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw== - -strip-dirs@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" - integrity sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g== - dependencies: - is-natural-number "^4.0.1" - strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" @@ -22401,11 +14313,6 @@ strip-final-newline@^2.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== -strip-final-newline@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" - integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== - strip-hex-prefix@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" @@ -22425,21 +14332,16 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" -strip-json-comments@2.0.1, strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== - -strip-json-comments@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" - integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== - -strip-json-comments@3.1.1, strip-json-comments@^3.1.1: +strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + strong-log-transformer@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz#0f5ed78d325e0421ac6f90f7f10e691d6ae3ae10" @@ -22454,51 +14356,6 @@ stubs@^3.0.0: resolved "https://registry.yarnpkg.com/stubs/-/stubs-3.0.0.tgz#e8d2ba1fa9c90570303c030b6900f7d5f89abe5b" integrity sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw== -sublevel-pouchdb@7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/sublevel-pouchdb/-/sublevel-pouchdb-7.3.1.tgz#c1cc03af45081345c7c82821d6dcaa74564ae2ef" - integrity sha512-n+4fK72F/ORdqPwoGgMGYeOrW2HaPpW9o9k80bT1B3Cim5BSvkKkr9WbWOWynni/GHkbCEdvLVFJL1ktosAdhQ== - dependencies: - inherits "2.0.4" - level-codec "9.0.2" - ltgt "2.2.1" - readable-stream "1.1.14" - -supports-color@5.4.0: - version "5.4.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" - integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== - dependencies: - has-flag "^3.0.0" - -supports-color@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" - integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg== - dependencies: - has-flag "^3.0.0" - -supports-color@7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" - integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== - dependencies: - has-flag "^4.0.0" - -supports-color@8.1.1, supports-color@^8.0.0, supports-color@^8.1.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - -supports-color@^3.1.0: - version "3.2.3" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" - integrity sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A== - dependencies: - has-flag "^1.0.0" - supports-color@^5.0.0, supports-color@^5.3.0, supports-color@^5.4.0, supports-color@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -22513,6 +14370,13 @@ supports-color@^7.0.0, supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +supports-color@^8.0.0, supports-color@^8.1.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + supports-hyperlinks@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-1.0.1.tgz#71daedf36cc1060ac5100c351bb3da48c29c0ef7" @@ -22542,24 +14406,6 @@ swap-case@^1.1.0: lower-case "^1.1.1" upper-case "^1.1.1" -swarm-js@0.1.39: - version "0.1.39" - resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.39.tgz#79becb07f291d4b2a178c50fee7aa6e10342c0e8" - integrity sha512-QLMqL2rzF6n5s50BptyD6Oi0R1aWlJC5Y17SRIVXRj6OR1DRIPM7nepvrxxkjA1zNzFz6mUOMjfeqeDaWB7OOg== - dependencies: - bluebird "^3.5.0" - buffer "^5.0.5" - decompress "^4.0.0" - eth-lib "^0.1.26" - fs-extra "^4.0.2" - got "^7.1.0" - mime-types "^2.1.16" - mkdirp-promise "^5.0.1" - mock-fs "^4.1.0" - setimmediate "^1.0.5" - tar "^4.0.2" - xhr-request-promise "^0.1.2" - swarm-js@^0.1.40: version "0.1.42" resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.42.tgz#497995c62df6696f6e22372f457120e43e727979" @@ -22577,58 +14423,6 @@ swarm-js@^0.1.40: tar "^4.0.2" xhr-request "^1.0.1" -symbol-observable@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" - integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== - -sync-request@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/sync-request/-/sync-request-6.1.0.tgz#e96217565b5e50bbffe179868ba75532fb597e68" - integrity sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw== - dependencies: - http-response-object "^3.0.1" - sync-rpc "^1.2.1" - then-request "^6.0.0" - -sync-rpc@^1.2.1: - version "1.3.6" - resolved "https://registry.yarnpkg.com/sync-rpc/-/sync-rpc-1.3.6.tgz#b2e8b2550a12ccbc71df8644810529deb68665a7" - integrity sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw== - dependencies: - get-port "^3.1.0" - -table@^5.2.3: - version "5.4.6" - resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" - integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== - dependencies: - ajv "^6.10.2" - lodash "^4.17.14" - slice-ansi "^2.1.0" - string-width "^3.0.0" - -tape@^4.4.0: - version "4.16.2" - resolved "https://registry.yarnpkg.com/tape/-/tape-4.16.2.tgz#7565e6af20426565557266e9dda7215869b297b6" - integrity sha512-TUChV+q0GxBBCEbfCYkGLkv8hDJYjMdSWdE0/Lr331sB389dsvFUHNV9ph5iQqKzt8Ss9drzcda/YeexclBFqg== - dependencies: - call-bind "~1.0.2" - deep-equal "~1.1.1" - defined "~1.0.1" - dotignore "~0.1.2" - for-each "~0.3.3" - glob "~7.2.3" - has "~1.0.3" - inherits "~2.0.4" - is-regex "~1.1.4" - minimist "~1.2.7" - object-inspect "~1.12.3" - resolve "~1.22.1" - resumer "~0.0.0" - string.prototype.trim "~1.2.7" - through "~2.3.8" - tar-fs@^1.8.1: version "1.16.3" resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.3.tgz#966a628841da2c4010406a82167cbd5e0c72d509" @@ -22649,7 +14443,7 @@ tar-fs@^2.0.0: pump "^3.0.0" tar-stream "^2.1.4" -tar-stream@^1.1.2, tar-stream@^1.5.2: +tar-stream@^1.1.2: version "1.6.2" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== @@ -22673,7 +14467,7 @@ tar-stream@^2.1.4, tar-stream@~2.2.0: inherits "^2.0.3" readable-stream "^3.1.1" -tar@^4.0.2, tar@^4.4.2: +tar@^4.0.2: version "4.4.19" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3" integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA== @@ -22716,15 +14510,6 @@ teeny-request@7.1.1: stream-events "^1.0.5" uuid "^8.0.0" -teeny-request@^3.11.3: - version "3.11.3" - resolved "https://registry.yarnpkg.com/teeny-request/-/teeny-request-3.11.3.tgz#335c629f7645e5d6599362df2f3230c4cbc23a55" - integrity sha512-CKncqSF7sH6p4rzCgkb/z/Pcos5efl0DmolzvlqRQUNcpRIruOhY9+T1FsIlyEbfWd7MsFpodROOwHYh2BaXzw== - dependencies: - https-proxy-agent "^2.2.1" - node-fetch "^2.2.0" - uuid "^3.3.2" - temp-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" @@ -22744,14 +14529,6 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" -test-value@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/test-value/-/test-value-2.1.0.tgz#11da6ff670f3471a73b625ca4f3fdcf7bb748291" - integrity sha512-+1epbAxtKeXttkGFMTX9H42oqzOTufR1ceCF+GYA5aOmvaPq9wd4PUS8329fn2RRLGNeUkgRLnVpycjx8DsO2w== - dependencies: - array-back "^1.0.3" - typical "^2.6.0" - testrpc@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/testrpc/-/testrpc-0.0.1.tgz#83e2195b1f5873aec7be1af8cbe6dcf39edb7aed" @@ -22762,42 +14539,6 @@ text-extensions@^1.0.0: resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26" integrity sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ== -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== - -then-request@^6.0.0: - version "6.0.2" - resolved "https://registry.yarnpkg.com/then-request/-/then-request-6.0.2.tgz#ec18dd8b5ca43aaee5cb92f7e4c1630e950d4f0c" - integrity sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA== - dependencies: - "@types/concat-stream" "^1.6.0" - "@types/form-data" "0.0.33" - "@types/node" "^8.0.0" - "@types/qs" "^6.2.31" - caseless "~0.12.0" - concat-stream "^1.6.0" - form-data "^2.2.0" - http-basic "^8.1.1" - http-response-object "^3.0.1" - promise "^8.0.0" - qs "^6.4.0" - -thenify-all@^1.0.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" - integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA== - dependencies: - thenify ">= 3.1.0 < 4" - -"thenify@>= 3.1.0 < 4": - version "3.3.1" - resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f" - integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== - dependencies: - any-promise "^1.0.0" - thriftrw@^3.5.0: version "3.11.4" resolved "https://registry.yarnpkg.com/thriftrw/-/thriftrw-3.11.4.tgz#84c990ee89e926631c0b475909ada44ee9249870" @@ -22807,14 +14548,6 @@ thriftrw@^3.5.0: error "7.0.2" long "^2.4.0" -through2@3.0.2, through2@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.2.tgz#99f88931cfc761ec7678b41d5d7336b5b6a07bf4" - integrity sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ== - dependencies: - inherits "^2.0.4" - readable-stream "2 || 3" - through2@^2.0.0: version "2.0.5" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" @@ -22823,14 +14556,6 @@ through2@^2.0.0: readable-stream "~2.3.6" xtend "~4.0.1" -through2@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.0.tgz#468b461df9cd9fcc170f22ebf6852e467e578ff2" - integrity sha512-8B+sevlqP4OiCjonI1Zw03Sf8PuV1eRsYQgLad5eonILOdyeRsY27A/2Ze8IlvlMvq31OH+3fz/styI7Ya62yQ== - dependencies: - readable-stream "2 || 3" - xtend "~4.0.1" - through2@^4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/through2/-/through2-4.0.2.tgz#a7ce3ac2a7a8b0b966c80e7c49f0484c3b239764" @@ -22838,27 +14563,15 @@ through2@^4.0.0: dependencies: readable-stream "3" -through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6, through@^2.3.8, through@~2.3.4, through@~2.3.8: +through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== - -timed-out@^4.0.0, timed-out@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" - integrity sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA== - -tiny-async-pool@^1.0.4: - version "1.3.0" - resolved "https://registry.yarnpkg.com/tiny-async-pool/-/tiny-async-pool-1.3.0.tgz#c013e1b369095e7005db5595f95e646cca6ef8a5" - integrity sha512-01EAw5EDrcVrdgyCLgoSPvqznC0sVxDSVeiOz09FUpjh71G79VCqneOr+xvt7T1r76CF6ZZfPjHorN2+d+3mqA== - dependencies: - semver "^5.5.0" + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== -tiny-emitter@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" - integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== +timed-out@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" + integrity sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA== tiny-secp256k1@2.2.1: version "2.2.1" @@ -22867,11 +14580,6 @@ tiny-secp256k1@2.2.1: dependencies: uint8array-tools "0.0.7" -tiny-typed-emitter@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz#b3b027fdd389ff81a152c8e847ee2f5be9fad7b5" - integrity sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA== - title-case@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/title-case/-/title-case-2.1.1.tgz#3e127216da58d2bc5becf137ab91dae3a7cd8faa" @@ -22923,11 +14631,6 @@ to-object-path@^0.3.0: dependencies: kind-of "^3.0.2" -to-readable-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" - integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== - to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" @@ -22958,7 +14661,7 @@ toidentifier@1.0.1: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== -tough-cookie@^2.3.3, tough-cookie@~2.5.0: +tough-cookie@~2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== @@ -22966,16 +14669,6 @@ tough-cookie@^2.3.3, tough-cookie@~2.5.0: psl "^1.1.28" punycode "^2.1.1" -"tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0": - version "4.1.2" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.2.tgz#e53e84b85f24e0b65dd526f46628db6c85f6b874" - integrity sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ== - dependencies: - psl "^1.1.33" - punycode "^2.1.1" - universalify "^0.2.0" - url-parse "^1.5.3" - tr46@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" @@ -23003,135 +14696,6 @@ trim-newlines@^3.0.0: resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw== -truffle-flattener@^1.4.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/truffle-flattener/-/truffle-flattener-1.6.0.tgz#abb64488b711e6cca0a9d3e449f6a85e35964c5d" - integrity sha512-scS5Bsi4CZyvlrmD4iQcLHTiG2RQFUXVheTgWeH6PuafmI+Lk5U87Es98loM3w3ImqC9/fPHq+3QIXbcPuoJ1Q== - dependencies: - "@resolver-engine/imports-fs" "^0.2.2" - "@solidity-parser/parser" "^0.14.1" - find-up "^2.1.0" - mkdirp "^1.0.4" - tsort "0.0.1" - -truffle-hdwallet-provider@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/truffle-hdwallet-provider/-/truffle-hdwallet-provider-0.0.3.tgz#0e1de02104b73d3875e1cf7093305b4ea8a2d843" - integrity sha512-oF00yd5jwGcHn0F063fhdE+pcw8No+idoX2vvR/3SuSJri54vdW/f/qBEc5BpJMjhVJtoAmw+ITI9ZhC+UJuFw== - dependencies: - bip39 "^2.2.0" - ethereumjs-wallet "^0.6.0" - web3 "^0.18.2" - web3-provider-engine "^8.4.0" - -truffle-plugin-verify@^0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/truffle-plugin-verify/-/truffle-plugin-verify-0.6.5.tgz#60110d39e8bc44301cb9b2aff81da8aa8308c177" - integrity sha512-8vFYVKe+L/tyhjyYb2aNwT7DFkN2BfQ+VSnmywCK2IbpGA0zRF7QYjRcne8UllpxcAVv0o4i1L97+qmN06ugnA== - dependencies: - "@truffle/resolver" "^9.0.35" - axios "^0.26.1" - cli-logger "^0.5.40" - delay "^5.0.0" - querystring "^0.2.1" - tunnel "0.0.6" - -truffle-security@^1.7.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/truffle-security/-/truffle-security-1.7.3.tgz#c9dd7a0e7f35adb36d40878fa6939cf9446d210d" - integrity sha512-eruRvUBTBwO3anVW5o8qCWf/TGDVnNsKbM9cS6bxSI99MfXh5G0jw3Sy5m8Xeq6P9Y0QkqrmO/Sb+67vaX9bAw== - dependencies: - "@truffle/artifactor" "^4.0.36" - "@truffle/compile-vyper" "^1.0.33" - "@truffle/config" "^1.2.6" - "@truffle/contract" "^4.0.37" - "@truffle/contract-sources" "^0.1.6" - "@truffle/error" "0.0.7" - "@truffle/expect" "0.0.12" - "@truffle/external-compile" "^1.0.19" - "@truffle/resolver" "^5.0.18" - armlet "^2.7.0" - configstore "^4.0.0" - debug "^4.1.1" - eslint "^5.16.0" - find-cache-dir "^2.1.0" - inquirer "^6.2.2" - js-yaml "^3.13.1" - lodash "^4.17.15" - mkdirp "^0.5.1" - mocha "^5.2.0" - multi-progress "^2.0.0" - mythxjs "^1.3.11" - proxyquire "^2.1.0" - remix-lib ">=0.4.1" - sleep "6.1.0" - solc "^0.5.8" - tiny-async-pool "^1.0.4" - uuid "^3.3.3" - -truffle-typings@^1.0.6: - version "1.0.8" - resolved "https://registry.yarnpkg.com/truffle-typings/-/truffle-typings-1.0.8.tgz#0b92d86a86a77c43771cdbce2544b67a25e3f2e2" - integrity sha512-75yFYNt0ws1TTehrGxhOqH3tutvBCAs+RG2SrhVIqQvU72kLAb4ercl32dES8yKbXBVHjzv3OXNg5gsbak+3Dg== - dependencies: - "@types/chai" "^4.1.4" - "@types/mocha" "^5.2.5" - "@types/web3" "^1.0.18" - -truffle@5.9.0: - version "5.9.0" - resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.9.0.tgz#55035fd092795a3ee8204656bfb593e71438fed2" - integrity sha512-XZBlGzU+IA0F3oDpmTWas62TYrNseG3xYh861zR+E09K2A0E0eSuTi1d5k+Uzhv4I6bIlNSWL31iI1J/PiZxcw== - dependencies: - "@truffle/db-loader" "^0.2.24" - "@truffle/debugger" "^11.1.0" - app-module-path "^2.2.0" - ganache "7.8.0" - mocha "10.1.0" - original-require "^1.0.1" - optionalDependencies: - "@truffle/db" "^2.0.24" - -ts-essentials@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-1.0.4.tgz#ce3b5dade5f5d97cf69889c11bf7d2da8555b15a" - integrity sha512-q3N1xS4vZpRouhYHDPwO0bDW3EZ6SK9CrrDHxi/D6BPReSjpVgWIOpLS2o0gSBZm+7q/wyKp6RVM1AeeW7uyfQ== - -ts-essentials@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-7.0.3.tgz#686fd155a02133eedcc5362dc8b5056cde3e5a38" - integrity sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ== - -ts-generator@^0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/ts-generator/-/ts-generator-0.0.8.tgz#7bd48ca064db026d9520bcb682b69efc20971d6a" - integrity sha512-Gi+aZCELpVL7Mqb+GuMgM+n8JZ/arZZib1iD/R9Ok8JDjOCOCrqS9b1lr72ku7J45WeDCFZxyJoRsiQvhokCnw== - dependencies: - "@types/mkdirp" "^0.5.2" - "@types/prettier" "^1.13.2" - "@types/resolve" "^0.0.8" - chalk "^2.4.1" - glob "^7.1.2" - mkdirp "^0.5.1" - prettier "^1.14.2" - resolve "^1.8.1" - ts-essentials "^1.0.0" - -ts-generator@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ts-generator/-/ts-generator-0.1.1.tgz#af46f2fb88a6db1f9785977e9590e7bcd79220ab" - integrity sha512-N+ahhZxTLYu1HNTQetwWcx3so8hcYbkKBHTr4b4/YgObFTIKkOSSsaa+nal12w8mfrJAyzJfETXawbNjSfP2gQ== - dependencies: - "@types/mkdirp" "^0.5.2" - "@types/prettier" "^2.1.1" - "@types/resolve" "^0.0.8" - chalk "^2.4.1" - glob "^7.1.2" - mkdirp "^0.5.1" - prettier "^2.1.2" - resolve "^1.8.1" - ts-essentials "^1.0.0" - ts-jest@^29.0.0: version "29.1.0" resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.1.0.tgz#4a9db4104a49b76d2b368ea775b6c9535c603891" @@ -23146,17 +14710,6 @@ ts-jest@^29.0.0: semver "7.x" yargs-parser "^21.0.1" -ts-node@8.10.2: - version "8.10.2" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.10.2.tgz#eee03764633b1234ddd37f8db9ec10b75ec7fb8d" - integrity sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA== - dependencies: - arg "^4.1.0" - diff "^4.0.1" - make-error "^1.1.1" - source-map-support "^0.5.17" - yn "3.1.1" - ts-node@^10.9.1: version "10.9.1" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" @@ -23215,11 +14768,6 @@ tslib@^2.6.2: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== -tslib@~2.4.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e" - integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA== - tslint-config-prettier@^1.18.0: version "1.18.0" resolved "https://registry.yarnpkg.com/tslint-config-prettier/-/tslint-config-prettier-1.18.0.tgz#75f140bde947d35d8f0d238e0ebf809d64592c37" @@ -23272,11 +14820,6 @@ tslint@^5.20.0: tslib "^1.8.0" tsutils "^2.29.0" -tsort@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" - integrity sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw== - "tsutils@^2.27.2 <2.29.0": version "2.28.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.28.0.tgz#6bd71e160828f9d019b6f4e844742228f85169a1" @@ -23311,11 +14854,6 @@ tty-table@^4.1.5: wcwidth "^1.0.1" yargs "^17.7.1" -tunnel-agent@^0.4.0: - version "0.4.3" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" - integrity sha512-e0IoVDWx8SDHc/hwFTqJDQ7CCDTEeGhmcT9jkWJjoGQSpgBz20nAMr80E3Tpk7PatJ1b37DQDgJR3CNSzcMOZQ== - tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -23323,24 +14861,12 @@ tunnel-agent@^0.6.0: dependencies: safe-buffer "^5.0.1" -tunnel@0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" - integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== - tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== - dependencies: - prelude-ls "~1.1.2" - -type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5: +type-detect@4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== @@ -23398,31 +14924,6 @@ type@^2.7.2: resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== -typechain-target-ethers-v5@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/typechain-target-ethers-v5/-/typechain-target-ethers-v5-5.0.1.tgz#a6b0ce6c2e8ff55f2d555d8ab55b9251ed9d211c" - integrity sha512-ag2fMLcXTZwtHSeDT6+QanmY7yVn3VSYBcqIGpj1A3Zp+d9Bmto5qM/eFXUsql4i9UBLgr3GVGgjkR6lz40QGQ== - -typechain-target-truffle@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/typechain-target-truffle/-/typechain-target-truffle-1.0.2.tgz#52ecbd8b7a854960567ad223660d60fcb42eaa17" - integrity sha512-XF3Iq2IzR+Pqvx6fcKIKGXNEk3lEcY24vYv9VqoVPfPB6vUM09PRLJCeLm1/ag6Pr2PICKUA0f4Es+YTR3ESKA== - dependencies: - lodash "^4.17.15" - -typechain@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/typechain/-/typechain-4.0.3.tgz#e8fcd6c984676858c64eeeb155ea783a10b73779" - integrity sha512-tmoHQeXZWHxIdeLK+i6dU0CU0vOd9Cndr3jFTZIMzak5/YpFZ8XoiYpTZcngygGBqZo+Z1EUmttLbW9KkFZLgQ== - dependencies: - command-line-args "^4.0.7" - debug "^4.1.1" - fs-extra "^7.0.0" - js-sha3 "^0.8.0" - lodash "^4.17.15" - ts-essentials "^7.0.1" - ts-generator "^0.1.1" - typed-array-buffer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60" @@ -23462,11 +14963,6 @@ typed-array-length@^1.0.4: for-each "^0.3.3" is-typed-array "^1.1.9" -typed-function@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/typed-function/-/typed-function-1.1.0.tgz#ea149706e0fb42aca1791c053a6d94ccd6c4fdcb" - integrity sha512-TuQzwiT4DDg19beHam3E66oRXhyqlyfgjHB/5fcvsRXbfmWPJfto9B4a0TBdTrQAPGlGmXh/k7iUI+WsObgORA== - typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" @@ -23514,18 +15010,6 @@ typeforce@^1.11.5: resolved "https://registry.yarnpkg.com/typeforce/-/typeforce-1.18.0.tgz#d7416a2c5845e085034d70fcc5b6cc4a90edbfdc" integrity sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g== -typescript-compare@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/typescript-compare/-/typescript-compare-0.0.2.tgz#7ee40a400a406c2ea0a7e551efd3309021d5f425" - integrity sha512-8ja4j7pMHkfLJQO2/8tut7ub+J3Lw2S3061eJLFQcvs3tsmJKp8KG5NtpLn7KcY2w08edF74BSVN7qJS0U6oHA== - dependencies: - typescript-logic "^0.0.0" - -typescript-logic@^0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/typescript-logic/-/typescript-logic-0.0.0.tgz#66ebd82a2548f2b444a43667bec120b496890196" - integrity sha512-zXFars5LUkI3zP492ls0VskH3TtdeHCqu0i7/duGt60i5IGPIpAHE/DWo5FqJ6EjQ15YKXrt+AETjv60Dat34Q== - typescript-tslint-plugin@^0.5.4: version "0.5.5" resolved "https://registry.yarnpkg.com/typescript-tslint-plugin/-/typescript-tslint-plugin-0.5.5.tgz#673875c43640251f1ab3d63745d7d49726ff961c" @@ -23535,18 +15019,6 @@ typescript-tslint-plugin@^0.5.4: mock-require "^3.0.3" vscode-languageserver "^5.2.1" -typescript-tuple@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/typescript-tuple/-/typescript-tuple-2.2.1.tgz#7d9813fb4b355f69ac55032e0363e8bb0f04dad2" - integrity sha512-Zcr0lbt8z5ZdEzERHAMAniTiIKerFCMgd7yjq1fPnDJ43et/k9twIFQMUYff9k5oXcsQ0WpvFcgzK2ZKASoW6Q== - dependencies: - typescript-compare "^0.0.2" - -typescript@4.4.3: - version "4.4.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.3.tgz#bdc5407caa2b109efd4f82fe130656f977a29324" - integrity sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA== - typescript@4.7.4: version "4.7.4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235" @@ -23557,11 +15029,6 @@ typescript@4.7.4: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== -typical@^2.6.0, typical@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/typical/-/typical-2.6.1.tgz#5c080e5d661cbbe38259d2e70a3c7253e873881d" - integrity sha512-ofhi8kjIje6npGozTip9Fr8iecmYfEbS06i0JnIg+rh51KakryWF4+jX8lLKZVhy6N+ID45WYSFCxPOdTWCzNg== - uglify-js@^3.1.4: version "3.17.4" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c" @@ -23587,24 +15054,6 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" -unbzip2-stream@^1.0.9: - version "1.4.3" - resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7" - integrity sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg== - dependencies: - buffer "^5.2.1" - through "^2.3.8" - -unc-path-regex@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" - integrity sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg== - -underscore@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" - integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== - underscore@>1.4.4: version "1.13.6" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.6.tgz#04786a1f589dc6c09f761fc5f45b89e935136441" @@ -23634,13 +15083,6 @@ unique-slug@^3.0.0: dependencies: imurmurhash "^0.1.4" -unique-string@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" - integrity sha512-ODgiYu03y5g76A1I9Gt0/chLCzQjvzDy7DsZGsLOE/1MrF6wriEskSncj1+/C58Xk/kPZDppSctDybCwOSaGAg== - dependencies: - crypto-random-string "^1.0.0" - universal-user-agent@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" @@ -23651,11 +15093,6 @@ universalify@^0.1.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== -universalify@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" - integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== - universalify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" @@ -23694,25 +15131,11 @@ upper-case-first@^1.1.0, upper-case-first@^1.1.2: dependencies: upper-case "^1.1.1" -upper-case-first@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/upper-case-first/-/upper-case-first-2.0.2.tgz#992c3273f882abd19d1e02894cc147117f844324" - integrity sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg== - dependencies: - tslib "^2.0.3" - upper-case@^1.0.3, upper-case@^1.1.0, upper-case@^1.1.1, upper-case@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" integrity sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA== -upper-case@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-2.0.2.tgz#d89810823faab1df1549b7d97a76f8662bae6f7a" - integrity sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg== - dependencies: - tslib "^2.0.3" - uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -23725,51 +15148,11 @@ urix@^0.1.0: resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg== -url-parse-lax@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" - integrity sha512-BVA4lR5PIviy2PMseNd2jbFQ+jwSwQGdJejf5ctd1rEXt0Ypd7yanUK9+lYechVlN5VaTJGsu2U/3MDDu6KgBA== - dependencies: - prepend-http "^1.0.1" - -url-parse-lax@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" - integrity sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ== - dependencies: - prepend-http "^2.0.0" - -url-parse@1.4.4: - version "1.4.4" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.4.tgz#cac1556e95faa0303691fec5cf9d5a1bc34648f8" - integrity sha512-/92DTTorg4JjktLNLe6GPS2/RvAd/RGr6LuktmWSMLEOa6rjnlrFXNgSbSmkNvCoL2T028A0a1JaJLzRMlFoHg== - dependencies: - querystringify "^2.0.0" - requires-port "^1.0.0" - -url-parse@^1.5.3: - version "1.5.10" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" - integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== - dependencies: - querystringify "^2.1.1" - requires-port "^1.0.0" - url-set-query@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" integrity sha512-3AChu4NiXquPfeckE5R5cGdiHCMWJx1dwCWOmWIL4KHAziJNOFIYJlpGFeKDvwLPHovZRCxK3cYlwzqI9Vp+Gg== -url-template@^2.0.8: - version "2.0.8" - resolved "https://registry.yarnpkg.com/url-template/-/url-template-2.0.8.tgz#fc565a3cccbff7730c775f5641f9555791439f21" - integrity sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw== - -url-to-options@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" - integrity sha512-0kQLIzG4fdk/G5NONku64rSH/x32NOA39LVQqlK8Le6lvTF6GGRJpqaQFGgU+CLwySIqBSMdwYM0sYcW9f6P4A== - url@0.10.3: version "0.10.3" resolved "https://registry.yarnpkg.com/url/-/url-0.10.3.tgz#021e4d9c7705f21bbf37d03ceb58767402774c64" @@ -23812,39 +15195,16 @@ utf-8-validate@^5.0.2: dependencies: node-gyp-build "^4.3.0" -utf8@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.1.tgz#2e01db02f7d8d0944f77104f1609eb0c304cf768" - integrity sha512-FzZp4f0vPa0AfWf+eav6hqZEqbn7TU1my/GUexpF9e0Afe/fnuLQvgdq5KgD3ggUpu3DpwRUGC0iS8q35eVBLQ== - utf8@3.0.0, utf8@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== -utf8@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.2.tgz#1fa0d9270e9be850d9b05027f63519bf46457d96" - integrity sha512-QXo+O/QkLP/x1nyi54uQiG0XrODxdysuQvE5dtVqv7F5K2Qb6FsN+qbr6KhF5wQ20tfcV3VQp0/2x1e1MRSPWg== - util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== -util.promisify@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.1.2.tgz#02b3dbadbb80071eee4c43aed58747afdfc516db" - integrity sha512-PBdZ03m1kBnQ5cjjO0ZvJMJS+QsbyIcFwi4hY4U76OQsCO9JrOYjbCFgIF76ccFg9xnJo7ZHPkqyj1GqmdS7MA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - for-each "^0.3.3" - has-proto "^1.0.1" - has-symbols "^1.0.3" - object.getownpropertydescriptors "^2.1.6" - safe-array-concat "^1.0.0" - util@^0.10.3: version "0.10.4" resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" @@ -23852,7 +15212,7 @@ util@^0.10.3: dependencies: inherits "2.0.3" -util@^0.12.0, util@^0.12.4, util@^0.12.5: +util@^0.12.4, util@^0.12.5: version "0.12.5" resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== @@ -23873,26 +15233,21 @@ uuid@2.0.1: resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.1.tgz#c2a30dedb3e535d72ccf82e343941a50ba8533ac" integrity sha512-nWg9+Oa3qD2CQzHIP4qKUqwNfzKn8P0LtFhotaCTFchsV7ZfDhAybeip/HZVeMIpZi9JgY1E3nUlwaCmZT1sEg== -uuid@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" - integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== - uuid@8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.0.0.tgz#bc6ccf91b5ff0ac07bbcdbf1c7c4e150db4dbb6c" integrity sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw== -uuid@8.3.2, uuid@^8.0.0, uuid@^8.3.0, uuid@^8.3.2: - version "8.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" - integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== - -uuid@^3.2.1, uuid@^3.3.2, uuid@^3.3.3: +uuid@^3.3.2: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== +uuid@^8.0.0, uuid@^8.3.0, uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + uuid@^9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" @@ -23917,11 +15272,6 @@ v8-to-istanbul@^9.0.1: "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^1.6.0" -valid-url@^1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200" - integrity sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA== - validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" @@ -23944,16 +15294,6 @@ validate-npm-package-name@^4.0.0: dependencies: builtins "^5.0.0" -value-or-promise@1.0.11: - version "1.0.11" - resolved "https://registry.yarnpkg.com/value-or-promise/-/value-or-promise-1.0.11.tgz#3e90299af31dd014fe843fe309cefa7c1d94b140" - integrity sha512-41BrgH+dIbCFXClcSapVs5M6GkENd3gQOJpEfPDNa71LsUGMXDL0jMWpI/Rh7WhX+Aalfz2TTS3Zt5pUsbnhLg== - -value-or-promise@^1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/value-or-promise/-/value-or-promise-1.0.12.tgz#0e5abfeec70148c78460a849f6b003ea7986f15c" - integrity sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q== - varint@^5.0.0: version "5.0.2" resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4" @@ -23973,20 +15313,6 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -viem@^1.0.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/viem/-/viem-1.19.0.tgz#e9f2b5084795d217c4adeb4b1c46d2afa949967c" - integrity sha512-Q4gU7D5KMZDK2rarQqjeqW7KmZRdfbDyP+bDlsu0Ia+IWR4Aali+dMbis1s3rC12OWdNfSR5MNmPCHoqoQa5ew== - dependencies: - "@adraffy/ens-normalize" "1.9.4" - "@noble/curves" "1.2.0" - "@noble/hashes" "1.3.2" - "@scure/bip32" "1.3.2" - "@scure/bip39" "1.2.1" - abitype "0.9.8" - isows "1.0.3" - ws "8.13.0" - viem@~1.5.4: version "1.5.4" resolved "https://registry.yarnpkg.com/viem/-/viem-1.5.4.tgz#4ba43cda4be5ec193d9f1c092955743705a37450" @@ -24034,21 +15360,11 @@ vscode-uri@^1.0.6: resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-1.0.8.tgz#9769aaececae4026fb6e22359cb38946580ded59" integrity sha512-obtSWTlbJ+a+TFRYGaUumtVwb+InIUVI0Lu0VBUAPmj2cU5JutEXg3xUE0c2J5Tcy7h2DEKVJBFi+Y9ZSFzzPQ== -vuvuzela@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/vuvuzela/-/vuvuzela-1.0.3.tgz#3be145e58271c73ca55279dd851f12a682114b0b" - integrity sha512-Tm7jR1xTzBbPW+6y1tknKiEhz04Wf/1iZkcTJjSFcpNko43+dFW6+OOeQe9taJIug3NdfUAjFKgUSyQrIKaDvQ== - walk-up-path@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/walk-up-path/-/walk-up-path-1.0.0.tgz#d4745e893dd5fd0dbb58dd0a4c6a33d9c9fec53e" integrity sha512-hwj/qMDUEjCU5h0xr90KGCf0tg0/LgJbmOWgrWKYlcJZM7XvquvUJZ0G/HMGr7F7OQMOUuPHWP9JpriinkAlkg== -walkdir@^0.3.0, walkdir@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/walkdir/-/walkdir-0.3.2.tgz#ac8437a288c295656848ebc19981ebc677a5f590" - integrity sha512-0Twghia4Z5wDGDYWURlhZmI47GvERMCsXIu0QZWVVZyW9ZjpbbZvD9Zy9M6cWiQQRRbAcYajIyKNavaZZDt1Uw== - walker@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" @@ -24063,11 +15379,6 @@ wcwidth@^1.0.0, wcwidth@^1.0.1: dependencies: defaults "^1.0.3" -weak-map@^1.0.5: - version "1.0.8" - resolved "https://registry.yarnpkg.com/weak-map/-/weak-map-1.0.8.tgz#394c18a9e8262e790544ed8b55c6a4ddad1cb1a3" - integrity sha512-lNR9aAefbGPpHO7AEnY0hCFjz1eTkWCXYvkTRrTHs9qv8zJp+SkVYpzfLIFXQQiG3tVvbNFQgVg2bQS8YGgxyw== - web-streams-polyfill@^3.0.3: version "3.2.1" resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6" @@ -24082,25 +15393,6 @@ web3-bzz@1.10.0: got "12.1.0" swarm-js "^0.1.40" -web3-bzz@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.2.2.tgz#a3b9f613c49fd3e120e0997088a73557d5adb724" - integrity sha512-b1O2ObsqUN1lJxmFSjvnEC4TsaCbmh7Owj3IAIWTKqL9qhVgx7Qsu5O9cD13pBiSPNZJ68uJPaKq380QB4NWeA== - dependencies: - "@types/node" "^10.12.18" - got "9.6.0" - swarm-js "0.1.39" - underscore "1.9.1" - -web3-bzz@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.8.1.tgz#81397be5ce262d03d82b92e9d8acc11f8a609ea1" - integrity sha512-dJJHS84nvpoxv6ijTMkdUSlRr5beCXNtx4UZcrFLHBva8dT63QEtKdLyDt2AyMJJdVzTCk78uir/6XtVWrdS6w== - dependencies: - "@types/node" "^12.12.6" - got "12.1.0" - swarm-js "^0.1.40" - web3-bzz@1.8.2: version "1.8.2" resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.8.2.tgz#67ea1c775874056250eece551ded22905ed08784" @@ -24110,17 +15402,6 @@ web3-bzz@1.8.2: got "12.1.0" swarm-js "^0.1.40" -web3-core-helpers@1.0.0-beta.55: - version "1.0.0-beta.55" - resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.55.tgz#832b8499889f9f514b1d174f00172fd3683d63de" - integrity sha512-suj9Xy/lIqajaYLJTEjr2rlFgu6hGYwChHmf8+qNrC2luZA6kirTamtB9VThWMxbywx7p0bqQFjW6zXogAgWhg== - dependencies: - "@babel/runtime" "^7.3.1" - lodash "^4.17.11" - web3-core "1.0.0-beta.55" - web3-eth-iban "1.0.0-beta.55" - web3-utils "1.0.0-beta.55" - web3-core-helpers@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.10.0.tgz#1016534c51a5df77ed4f94d1fcce31de4af37fad" @@ -24129,23 +15410,6 @@ web3-core-helpers@1.10.0: web3-eth-iban "1.10.0" web3-utils "1.10.0" -web3-core-helpers@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.2.2.tgz#484974f4bd4a487217b85b0d7cfe841af0907619" - integrity sha512-HJrRsIGgZa1jGUIhvGz4S5Yh6wtOIo/TMIsSLe+Xay+KVnbseJpPprDI5W3s7H2ODhMQTbogmmUFquZweW2ImQ== - dependencies: - underscore "1.9.1" - web3-eth-iban "1.2.2" - web3-utils "1.2.2" - -web3-core-helpers@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.8.1.tgz#7904747b23fd0afa4f2c86ed98ea9418ccad7672" - integrity sha512-ClzNO6T1S1gifC+BThw0+GTfcsjLEY8T1qUp6Ly2+w4PntAdNtKahxWKApWJ0l9idqot/fFIDXwO3Euu7I0Xqw== - dependencies: - web3-eth-iban "1.8.1" - web3-utils "1.8.1" - web3-core-helpers@1.8.2: version "1.8.2" resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.8.2.tgz#82066560f8085e6c7b93bcc8e88b441289ea9f9f" @@ -24154,20 +15418,6 @@ web3-core-helpers@1.8.2: web3-eth-iban "1.8.2" web3-utils "1.8.2" -web3-core-method@1.0.0-beta.55: - version "1.0.0-beta.55" - resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.0.0-beta.55.tgz#0af994295ac2dd64ccd53305b7df8da76e11da49" - integrity sha512-w1cW/s2ji9qGELHk2uMJCn1ooay0JJLVoPD1nvmsW6OTRWcVjxa62nJrFQhe6P5lEb83Xk9oHgmCxZoVUHibOw== - dependencies: - "@babel/runtime" "^7.3.1" - eventemitter3 "3.1.0" - lodash "^4.17.11" - rxjs "^6.4.0" - web3-core "1.0.0-beta.55" - web3-core-helpers "1.0.0-beta.55" - web3-core-subscriptions "1.0.0-beta.55" - web3-utils "1.0.0-beta.55" - web3-core-method@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.10.0.tgz#82668197fa086e8cc8066742e35a9d72535e3412" @@ -24179,28 +15429,6 @@ web3-core-method@1.10.0: web3-core-subscriptions "1.10.0" web3-utils "1.10.0" -web3-core-method@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.2.2.tgz#d4fe2bb1945b7152e5f08e4ea568b171132a1e56" - integrity sha512-szR4fDSBxNHaF1DFqE+j6sFR/afv9Aa36OW93saHZnrh+iXSrYeUUDfugeNcRlugEKeUCkd4CZylfgbK2SKYJA== - dependencies: - underscore "1.9.1" - web3-core-helpers "1.2.2" - web3-core-promievent "1.2.2" - web3-core-subscriptions "1.2.2" - web3-utils "1.2.2" - -web3-core-method@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.8.1.tgz#0fc5a433a9fc784c447522f141c0a8e0163c7790" - integrity sha512-oYGRodktfs86NrnFwaWTbv2S38JnpPslFwSSARwFv4W9cjbGUW3LDeA5MKD/dRY+ssZ5OaekeMsUCLoGhX68yA== - dependencies: - "@ethersproject/transactions" "^5.6.2" - web3-core-helpers "1.8.1" - web3-core-promievent "1.8.1" - web3-core-subscriptions "1.8.1" - web3-utils "1.8.1" - web3-core-method@1.8.2: version "1.8.2" resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.8.2.tgz#ba5ec68084e903f0516415010477618be017eac2" @@ -24219,21 +15447,6 @@ web3-core-promievent@1.10.0: dependencies: eventemitter3 "4.0.4" -web3-core-promievent@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.2.2.tgz#3b60e3f2a0c96db8a891c927899d29d39e66ab1c" - integrity sha512-tKvYeT8bkUfKABcQswK6/X79blKTKYGk949urZKcLvLDEaWrM3uuzDwdQT3BNKzQ3vIvTggFPX9BwYh0F1WwqQ== - dependencies: - any-promise "1.3.0" - eventemitter3 "3.1.2" - -web3-core-promievent@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.8.1.tgz#f334c8b2ceac6c2228f06d2a515f6d103157f036" - integrity sha512-9mxqHlgB0MrZI4oUIRFkuoJMNj3E7btjrMv3sMer/Z9rYR1PfoSc1aAokw4rxKIcAh+ylVtd/acaB2HKB7aRPg== - dependencies: - eventemitter3 "4.0.4" - web3-core-promievent@1.8.2: version "1.8.2" resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.8.2.tgz#e670d6b4453632e6ecfd9ad82da44f77ac1585c9" @@ -24252,28 +15465,6 @@ web3-core-requestmanager@1.10.0: web3-providers-ipc "1.10.0" web3-providers-ws "1.10.0" -web3-core-requestmanager@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.2.2.tgz#667ba9ac724c9c76fa8965ae8a3c61f66e68d8d6" - integrity sha512-a+gSbiBRHtHvkp78U2bsntMGYGF2eCb6219aMufuZWeAZGXJ63Wc2321PCbA8hF9cQrZI4EoZ4kVLRI4OF15Hw== - dependencies: - underscore "1.9.1" - web3-core-helpers "1.2.2" - web3-providers-http "1.2.2" - web3-providers-ipc "1.2.2" - web3-providers-ws "1.2.2" - -web3-core-requestmanager@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.8.1.tgz#272ffa55b7b568ecbc8e4a257ca080355c31c60e" - integrity sha512-x+VC2YPPwZ1khvqA6TA69LvfFCOZXsoUVOxmTx/vIN22PrY9KzKhxcE7pBSiGhmab1jtmRYXUbcQSVpAXqL8cw== - dependencies: - util "^0.12.0" - web3-core-helpers "1.8.1" - web3-providers-http "1.8.1" - web3-providers-ipc "1.8.1" - web3-providers-ws "1.8.1" - web3-core-requestmanager@1.8.2: version "1.8.2" resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.8.2.tgz#dda95e83ca4808949612a41e54ecea557f78ef26" @@ -24285,15 +15476,6 @@ web3-core-requestmanager@1.8.2: web3-providers-ipc "1.8.2" web3-providers-ws "1.8.2" -web3-core-subscriptions@1.0.0-beta.55: - version "1.0.0-beta.55" - resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.55.tgz#105902c13db53466fc17d07a981ad3d41c700f76" - integrity sha512-pb3oQbUzK7IoyXwag8TYInQddg0rr7BHxKc+Pbs/92hVNQ5ps4iGMVJKezdrjlQ1IJEEUiDIglXl4LZ1hIuMkw== - dependencies: - "@babel/runtime" "^7.3.1" - eventemitter3 "^3.1.0" - lodash "^4.17.11" - web3-core-subscriptions@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.10.0.tgz#b534592ee1611788fc0cb0b95963b9b9b6eacb7c" @@ -24302,23 +15484,6 @@ web3-core-subscriptions@1.10.0: eventemitter3 "4.0.4" web3-core-helpers "1.10.0" -web3-core-subscriptions@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.2.2.tgz#bf4ba23a653a003bdc3551649958cc0b080b068e" - integrity sha512-QbTgigNuT4eicAWWr7ahVpJyM8GbICsR1Ys9mJqzBEwpqS+RXTRVSkwZ2IsxO+iqv6liMNwGregbJLq4urMFcQ== - dependencies: - eventemitter3 "3.1.2" - underscore "1.9.1" - web3-core-helpers "1.2.2" - -web3-core-subscriptions@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.8.1.tgz#f5ae1380e92746eadfab6475b8a70ef5a1be6bbf" - integrity sha512-bmCMq5OeA3E2vZUh8Js1HcJbhwtsE+yeMqGC4oIZB3XsL5SLqyKLB/pU+qUYqQ9o4GdcrFTDPhPg1bgvf7p1Pw== - dependencies: - eventemitter3 "4.0.4" - web3-core-helpers "1.8.1" - web3-core-subscriptions@1.8.2: version "1.8.2" resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.8.2.tgz#0c8bd49439d83c6f0a03c70f00b24a915a70a5ed" @@ -24327,19 +15492,6 @@ web3-core-subscriptions@1.8.2: eventemitter3 "4.0.4" web3-core-helpers "1.8.2" -web3-core@1.0.0-beta.55: - version "1.0.0-beta.55" - resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.0.0-beta.55.tgz#26b9abbf1bc1837c9cc90f06ecbc4ed714f89b53" - integrity sha512-AMMp7TLEtE7u8IJAu/THrRhBTZyZzeo7Y6GiWYNwb5+KStC9hIGLr9cI1KX9R6ZioTOLRHrqT7awDhnJ1ku2mg== - dependencies: - "@babel/runtime" "^7.3.1" - "@types/bn.js" "^4.11.4" - "@types/node" "^10.12.18" - lodash "^4.17.11" - web3-core-method "1.0.0-beta.55" - web3-providers "1.0.0-beta.55" - web3-utils "1.0.0-beta.55" - web3-core@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.10.0.tgz#9aa07c5deb478cf356c5d3b5b35afafa5fa8e633" @@ -24353,31 +15505,6 @@ web3-core@1.10.0: web3-core-requestmanager "1.10.0" web3-utils "1.10.0" -web3-core@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.2.2.tgz#334b99c8222ef9cfd0339e27352f0b58ea789a2f" - integrity sha512-miHAX3qUgxV+KYfaOY93Hlc3kLW2j5fH8FJy6kSxAv+d4d5aH0wwrU2IIoJylQdT+FeenQ38sgsCnFu9iZ1hCQ== - dependencies: - "@types/bn.js" "^4.11.4" - "@types/node" "^12.6.1" - web3-core-helpers "1.2.2" - web3-core-method "1.2.2" - web3-core-requestmanager "1.2.2" - web3-utils "1.2.2" - -web3-core@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.8.1.tgz#050b1c408d1f9b7ae539e90f7f7d1b7a7d10578b" - integrity sha512-LbRZlJH2N6nS3n3Eo9Y++25IvzMY7WvYnp4NM/Ajhh97dAdglYs6rToQ2DbL2RLvTYmTew4O/y9WmOk4nq9COw== - dependencies: - "@types/bn.js" "^5.1.0" - "@types/node" "^12.12.6" - bignumber.js "^9.0.0" - web3-core-helpers "1.8.1" - web3-core-method "1.8.1" - web3-core-requestmanager "1.8.1" - web3-utils "1.8.1" - web3-core@1.8.2: version "1.8.2" resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.8.2.tgz#333e93d7872b1a36efe758ed8b89a7acbdd962c2" @@ -24399,24 +15526,7 @@ web3-eth-abi@1.10.0: "@ethersproject/abi" "^5.6.3" web3-utils "1.10.0" -web3-eth-abi@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.2.2.tgz#d5616d88a90020f894763423a9769f2da11fe37a" - integrity sha512-Yn/ZMgoOLxhTVxIYtPJ0eS6pnAnkTAaJgUJh1JhZS4ekzgswMfEYXOwpMaD5eiqPJLpuxmZFnXnBZlnQ1JMXsw== - dependencies: - ethers "4.0.0-beta.3" - underscore "1.9.1" - web3-utils "1.2.2" - -web3-eth-abi@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.8.1.tgz#47455d6513217c4b0866fea6f97b1c4afa0b6535" - integrity sha512-0mZvCRTIG0UhDhJwNQJgJxu4b4DyIpuMA0GTfqxqeuqzX4Q/ZvmoNurw0ExTfXaGPP82UUmmdkRi6FdZOx+C6w== - dependencies: - "@ethersproject/abi" "^5.6.3" - web3-utils "1.8.1" - -web3-eth-abi@1.8.2, web3-eth-abi@^1.0.0-beta.24: +web3-eth-abi@1.8.2: version "1.8.2" resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.8.2.tgz#16e1e9be40e2527404f041a4745111211488f31a" integrity sha512-Om9g3kaRNjqiNPAgKwGT16y+ZwtBzRe4ZJFGjLiSs6v5I7TPNF+rRMWuKnR6jq0azQZDj6rblvKFMA49/k48Og== @@ -24440,41 +15550,6 @@ web3-eth-accounts@1.10.0: web3-core-method "1.10.0" web3-utils "1.10.0" -web3-eth-accounts@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.2.2.tgz#c187e14bff6baa698ac352220290222dbfd332e5" - integrity sha512-KzHOEyXOEZ13ZOkWN3skZKqSo5f4Z1ogPFNn9uZbKCz+kSp+gCAEKxyfbOsB/JMAp5h7o7pb6eYsPCUBJmFFiA== - dependencies: - any-promise "1.3.0" - crypto-browserify "3.12.0" - eth-lib "0.2.7" - ethereumjs-common "^1.3.2" - ethereumjs-tx "^2.1.1" - scrypt-shim "github:web3-js/scrypt-shim" - underscore "1.9.1" - uuid "3.3.2" - web3-core "1.2.2" - web3-core-helpers "1.2.2" - web3-core-method "1.2.2" - web3-utils "1.2.2" - -web3-eth-accounts@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.8.1.tgz#1ce7387721f118aeb0376291e4d8bbe2ac323406" - integrity sha512-mgzxSYgN54/NsOFBO1Fq1KkXp1S5KlBvI/DlgvajU72rupoFMq6Cu6Yp9GUaZ/w2ij9PzEJuFJk174XwtfMCmg== - dependencies: - "@ethereumjs/common" "2.5.0" - "@ethereumjs/tx" "3.3.2" - crypto-browserify "3.12.0" - eth-lib "0.2.8" - ethereumjs-util "^7.0.10" - scrypt-js "^3.0.1" - uuid "^9.0.0" - web3-core "1.8.1" - web3-core-helpers "1.8.1" - web3-core-method "1.8.1" - web3-utils "1.8.1" - web3-eth-accounts@1.8.2: version "1.8.2" resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.8.2.tgz#b894f5d5158fcae429da42de75d96520d0712971" @@ -24491,19 +15566,6 @@ web3-eth-accounts@1.8.2: web3-core-method "1.8.2" web3-utils "1.8.2" -web3-eth-admin@1.0.0-beta.55: - version "1.0.0-beta.55" - resolved "https://registry.yarnpkg.com/web3-eth-admin/-/web3-eth-admin-1.0.0-beta.55.tgz#dcbcc5be4e3a008ce367c2ac83432b9a711f39e9" - integrity sha512-7IbnTsIJ5zx5K/Nw5f8u1cFj6qwgTAdr/1MlL2/V5gE8IsO2qsSjbPHDZEawbgfpCLGuoHpOnUDIrce/HOYHbw== - dependencies: - "@babel/runtime" "^7.3.1" - web3-core "1.0.0-beta.55" - web3-core-helpers "1.0.0-beta.55" - web3-core-method "1.0.0-beta.55" - web3-net "1.0.0-beta.55" - web3-providers "1.0.0-beta.55" - web3-utils "1.0.0-beta.55" - web3-eth-contract@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.10.0.tgz#8e68c7654576773ec3c91903f08e49d0242c503a" @@ -24518,35 +15580,6 @@ web3-eth-contract@1.10.0: web3-eth-abi "1.10.0" web3-utils "1.10.0" -web3-eth-contract@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.2.2.tgz#84e92714918a29e1028ee7718f0712536e14e9a1" - integrity sha512-EKT2yVFws3FEdotDQoNsXTYL798+ogJqR2//CaGwx3p0/RvQIgfzEwp8nbgA6dMxCsn9KOQi7OtklzpnJMkjtA== - dependencies: - "@types/bn.js" "^4.11.4" - underscore "1.9.1" - web3-core "1.2.2" - web3-core-helpers "1.2.2" - web3-core-method "1.2.2" - web3-core-promievent "1.2.2" - web3-core-subscriptions "1.2.2" - web3-eth-abi "1.2.2" - web3-utils "1.2.2" - -web3-eth-contract@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.8.1.tgz#bdf3e33bbcb79a1b6144dffd6a0deefd2e459272" - integrity sha512-1wphnl+/xwCE2io44JKnN+ti3oa47BKRiVzvWd42icwRbcpFfRxH9QH+aQX3u8VZIISNH7dAkTWpGIIJgGFTmg== - dependencies: - "@types/bn.js" "^5.1.0" - web3-core "1.8.1" - web3-core-helpers "1.8.1" - web3-core-method "1.8.1" - web3-core-promievent "1.8.1" - web3-core-subscriptions "1.8.1" - web3-eth-abi "1.8.1" - web3-utils "1.8.1" - web3-eth-contract@1.8.2: version "1.8.2" resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.8.2.tgz#5388b7130923d2b790c09a420391a81312a867fb" @@ -24569,39 +15602,11 @@ web3-eth-ens@1.10.0: content-hash "^2.5.2" eth-ens-namehash "2.0.8" web3-core "1.10.0" - web3-core-helpers "1.10.0" - web3-core-promievent "1.10.0" - web3-eth-abi "1.10.0" - web3-eth-contract "1.10.0" - web3-utils "1.10.0" - -web3-eth-ens@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.2.2.tgz#0a4abed1d4cbdacbf5e1ab06e502d806d1192bc6" - integrity sha512-CFjkr2HnuyMoMFBoNUWojyguD4Ef+NkyovcnUc/iAb9GP4LHohKrODG4pl76R5u61TkJGobC2ij6TyibtsyVYg== - dependencies: - eth-ens-namehash "2.0.8" - underscore "1.9.1" - web3-core "1.2.2" - web3-core-helpers "1.2.2" - web3-core-promievent "1.2.2" - web3-eth-abi "1.2.2" - web3-eth-contract "1.2.2" - web3-utils "1.2.2" - -web3-eth-ens@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.8.1.tgz#e78a9651fea8282abe8565b001819e2d645e5929" - integrity sha512-FT8xTI9uN8RxeBQa/W8pLa2aoFh4+EE34w7W2271LICKzla1dtLyb6XSdn48vsUcPmhWsTVk9mO9RTU0l4LGQQ== - dependencies: - content-hash "^2.5.2" - eth-ens-namehash "2.0.8" - web3-core "1.8.1" - web3-core-helpers "1.8.1" - web3-core-promievent "1.8.1" - web3-eth-abi "1.8.1" - web3-eth-contract "1.8.1" - web3-utils "1.8.1" + web3-core-helpers "1.10.0" + web3-core-promievent "1.10.0" + web3-eth-abi "1.10.0" + web3-eth-contract "1.10.0" + web3-utils "1.10.0" web3-eth-ens@1.8.2: version "1.8.2" @@ -24617,15 +15622,6 @@ web3-eth-ens@1.8.2: web3-eth-contract "1.8.2" web3-utils "1.8.2" -web3-eth-iban@1.0.0-beta.55: - version "1.0.0-beta.55" - resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.55.tgz#15146a69de21addc99e7dbfb2920555b1e729637" - integrity sha512-a2Fxsb5Mssa+jiXgjUdIzJipE0175IcQXJbZLpKft2+zeSJWNTbaa3PQD2vPPpIM4W789q06N+f9Zc0Fyls+1g== - dependencies: - "@babel/runtime" "^7.3.1" - bn.js "4.11.8" - web3-utils "1.0.0-beta.55" - web3-eth-iban@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.10.0.tgz#5a46646401965b0f09a4f58e7248c8a8cd22538a" @@ -24634,22 +15630,6 @@ web3-eth-iban@1.10.0: bn.js "^5.2.1" web3-utils "1.10.0" -web3-eth-iban@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.2.2.tgz#76bec73bad214df7c4192388979a59fc98b96c5a" - integrity sha512-gxKXBoUhaTFHr0vJB/5sd4i8ejF/7gIsbM/VvemHT3tF5smnmY6hcwSMmn7sl5Gs+83XVb/BngnnGkf+I/rsrQ== - dependencies: - bn.js "4.11.8" - web3-utils "1.2.2" - -web3-eth-iban@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.8.1.tgz#c6484e5d68ca644aa78431301e7acd5df24598d1" - integrity sha512-DomoQBfvIdtM08RyMGkMVBOH0vpOIxSSQ+jukWk/EkMLGMWJtXw/K2c2uHAeq3L/VPWNB7zXV2DUEGV/lNE2Dg== - dependencies: - bn.js "^5.2.1" - web3-utils "1.8.1" - web3-eth-iban@1.8.2: version "1.8.2" resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.8.2.tgz#5cb3022234b13986f086353b53f0379a881feeaf" @@ -24670,30 +15650,6 @@ web3-eth-personal@1.10.0: web3-net "1.10.0" web3-utils "1.10.0" -web3-eth-personal@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.2.2.tgz#eee1c86a8132fa16b5e34c6d421ca92e684f0be6" - integrity sha512-4w+GLvTlFqW3+q4xDUXvCEMU7kRZ+xm/iJC8gm1Li1nXxwwFbs+Y+KBK6ZYtoN1qqAnHR+plYpIoVo27ixI5Rg== - dependencies: - "@types/node" "^12.6.1" - web3-core "1.2.2" - web3-core-helpers "1.2.2" - web3-core-method "1.2.2" - web3-net "1.2.2" - web3-utils "1.2.2" - -web3-eth-personal@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.8.1.tgz#00b5ff1898b62044d25ed5fddd8486168d4827cf" - integrity sha512-myIYMvj7SDIoV9vE5BkVdon3pya1WinaXItugoii2VoTcQNPOtBxmYVH+XS5ErzCJlnxzphpQrkywyY64bbbCA== - dependencies: - "@types/node" "^12.12.6" - web3-core "1.8.1" - web3-core-helpers "1.8.1" - web3-core-method "1.8.1" - web3-net "1.8.1" - web3-utils "1.8.1" - web3-eth-personal@1.8.2: version "1.8.2" resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.8.2.tgz#3526c1ebaa4e7bf3a0a8ec77e34f067cc9a750b2" @@ -24724,43 +15680,6 @@ web3-eth@1.10.0: web3-net "1.10.0" web3-utils "1.10.0" -web3-eth@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.2.2.tgz#65a1564634a23b990efd1655bf94ad513904286c" - integrity sha512-UXpC74mBQvZzd4b+baD4Ocp7g+BlwxhBHumy9seyE/LMIcMlePXwCKzxve9yReNpjaU16Mmyya6ZYlyiKKV8UA== - dependencies: - underscore "1.9.1" - web3-core "1.2.2" - web3-core-helpers "1.2.2" - web3-core-method "1.2.2" - web3-core-subscriptions "1.2.2" - web3-eth-abi "1.2.2" - web3-eth-accounts "1.2.2" - web3-eth-contract "1.2.2" - web3-eth-ens "1.2.2" - web3-eth-iban "1.2.2" - web3-eth-personal "1.2.2" - web3-net "1.2.2" - web3-utils "1.2.2" - -web3-eth@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.8.1.tgz#395f6cd56edaac5dbb23e8cec9886c3fd32c430e" - integrity sha512-LgyzbhFqiFRd8M8sBXoFN4ztzOnkeckl3H/9lH5ek7AdoRMhBg7tYpYRP3E5qkhd/q+yiZmcUgy1AF6NHrC1wg== - dependencies: - web3-core "1.8.1" - web3-core-helpers "1.8.1" - web3-core-method "1.8.1" - web3-core-subscriptions "1.8.1" - web3-eth-abi "1.8.1" - web3-eth-accounts "1.8.1" - web3-eth-contract "1.8.1" - web3-eth-ens "1.8.1" - web3-eth-iban "1.8.1" - web3-eth-personal "1.8.1" - web3-net "1.8.1" - web3-utils "1.8.1" - web3-eth@1.8.2: version "1.8.2" resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.8.2.tgz#8562287ae1803c30eb54dc7d832092e5739ce06a" @@ -24779,19 +15698,6 @@ web3-eth@1.8.2: web3-net "1.8.2" web3-utils "1.8.2" -web3-net@1.0.0-beta.55: - version "1.0.0-beta.55" - resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.0.0-beta.55.tgz#daf24323df16a890a0bac6c6eda48b6e8c7e96ef" - integrity sha512-do2WY8+/GArJSWX7k/zZ7nBnV9Y3n6LhPYkwT3LeFqDzD515bKwlomaNC8hOaTc6UQyXIoPprYTK2FevL7jrZw== - dependencies: - "@babel/runtime" "^7.3.1" - lodash "^4.17.11" - web3-core "1.0.0-beta.55" - web3-core-helpers "1.0.0-beta.55" - web3-core-method "1.0.0-beta.55" - web3-providers "1.0.0-beta.55" - web3-utils "1.0.0-beta.55" - web3-net@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.10.0.tgz#be53e7f5dafd55e7c9013d49c505448b92c9c97b" @@ -24801,24 +15707,6 @@ web3-net@1.10.0: web3-core-method "1.10.0" web3-utils "1.10.0" -web3-net@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.2.2.tgz#5c3226ca72df7c591422440ce6f1203fd42ddad9" - integrity sha512-K07j2DXq0x4UOJgae65rWZKraOznhk8v5EGSTdFqASTx7vWE/m+NqBijBYGEsQY1lSMlVaAY9UEQlcXK5HzXTw== - dependencies: - web3-core "1.2.2" - web3-core-method "1.2.2" - web3-utils "1.2.2" - -web3-net@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.8.1.tgz#2bed4d4b93166724129ec33d0e5dea98880285f4" - integrity sha512-LyEJAwogdFo0UAXZqoSJGFjopdt+kLw0P00FSZn2yszbgcoI7EwC+nXiOsEe12xz4LqpYLOtbR7+gxgiTVjjHQ== - dependencies: - web3-core "1.8.1" - web3-core-method "1.8.1" - web3-utils "1.8.1" - web3-net@1.8.2: version "1.8.2" resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.8.2.tgz#97e1e0015fabc4cda31017813e98d0b5468dd04f" @@ -24828,80 +15716,6 @@ web3-net@1.8.2: web3-core-method "1.8.2" web3-utils "1.8.2" -web3-provider-engine@16.0.4: - version "16.0.4" - resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-16.0.4.tgz#a6565d85f3cfdc2da68f141af8728f90ad198f3f" - integrity sha512-f5WxJ9+LTF+4aJo4tCOXtQ6SDytBtLkhvV+qh/9gImHAuG9sMr6utY0mn/pro1Rx7O3hbztBxvQKjGMdOo8muw== - dependencies: - "@ethereumjs/tx" "^3.3.0" - async "^2.5.0" - backoff "^2.5.0" - clone "^2.0.0" - eth-block-tracker "^4.4.2" - eth-json-rpc-filters "^4.2.1" - eth-json-rpc-infura "^5.1.0" - eth-json-rpc-middleware "^6.0.0" - eth-rpc-errors "^3.0.0" - eth-sig-util "^1.4.2" - ethereumjs-block "^1.2.2" - ethereumjs-util "^5.1.5" - ethereumjs-vm "^2.3.4" - json-stable-stringify "^1.0.1" - promise-to-callback "^1.0.0" - readable-stream "^2.2.9" - request "^2.85.0" - semaphore "^1.0.3" - ws "^5.1.1" - xhr "^2.2.0" - xtend "^4.0.1" - -web3-provider-engine@^16.0.5: - version "16.0.5" - resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-16.0.5.tgz#28a0eaf6c33bc60b3cb7de1b961bea6b5cf06b78" - integrity sha512-fvoMm8Tehf3efaqv9pSd2VKLjgzcYNsJaiby87nPrktlnIc9S3G/9udnuJQn32FAt19yzOvNk3B513jhBKOgEg== - dependencies: - "@ethereumjs/tx" "^3.3.0" - async "^2.5.0" - backoff "^2.5.0" - clone "^2.0.0" - eth-block-tracker "^5.0.1" - eth-json-rpc-filters "^4.2.1" - eth-json-rpc-infura "^5.1.0" - eth-json-rpc-middleware "^6.0.0" - eth-rpc-errors "^3.0.0" - eth-sig-util "^1.4.2" - ethereumjs-block "^1.2.2" - ethereumjs-util "^5.1.5" - ethereumjs-vm "^2.3.4" - json-stable-stringify "^1.0.1" - promise-to-callback "^1.0.0" - readable-stream "^2.2.9" - request "^2.85.0" - semaphore "^1.0.3" - ws "^5.1.1" - xhr "^2.2.0" - xtend "^4.0.1" - -web3-provider-engine@^8.4.0: - version "8.6.1" - resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-8.6.1.tgz#4d86e19e30caaf97df351511ec0f60136e5b30eb" - integrity sha512-atTQJ14QBvd5N+71DKZHKCjHqCXfYQEcisLJHsZwvPmU5F3oRMydBXFmPU3sySHXgxASbV7Q9eEQAaPy+7rcHA== - dependencies: - async "^2.1.2" - clone "^2.0.0" - ethereumjs-block "^1.2.2" - ethereumjs-tx "^1.2.0" - ethereumjs-util "^5.0.1" - ethereumjs-vm "^2.0.2" - isomorphic-fetch "^2.2.0" - request "^2.67.0" - semaphore "^1.0.3" - solc "^0.4.2" - tape "^4.4.0" - web3 "^0.16.0" - xhr "^2.2.0" - xtend "^4.0.1" - web3-providers-http@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.10.0.tgz#864fa48675e7918c9a4374e5f664b32c09d0151b" @@ -24912,24 +15726,6 @@ web3-providers-http@1.10.0: es6-promise "^4.2.8" web3-core-helpers "1.10.0" -web3-providers-http@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.2.2.tgz#155e55c1d69f4c5cc0b411ede40dea3d06720956" - integrity sha512-BNZ7Hguy3eBszsarH5gqr9SIZNvqk9eKwqwmGH1LQS1FL3NdoOn7tgPPdddrXec4fL94CwgNk4rCU+OjjZRNDg== - dependencies: - web3-core-helpers "1.2.2" - xhr2-cookies "1.1.0" - -web3-providers-http@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.8.1.tgz#8aa89c11a9272f11ddb74b871273c92225faa28d" - integrity sha512-1Zyts4O9W/UNEPkp+jyL19Jc3D15S4yp8xuLTjVhcUEAlHo24NDWEKxtZGUuHk4HrKL2gp8OlsDbJ7MM+ESDgg== - dependencies: - abortcontroller-polyfill "^1.7.3" - cross-fetch "^3.1.4" - es6-promise "^4.2.8" - web3-core-helpers "1.8.1" - web3-providers-http@1.8.2: version "1.8.2" resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.8.2.tgz#fbda3a3bbc8db004af36e91bec35f80273b37885" @@ -24948,23 +15744,6 @@ web3-providers-ipc@1.10.0: oboe "2.1.5" web3-core-helpers "1.10.0" -web3-providers-ipc@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.2.2.tgz#c6d165a12bc68674b4cdd543ea18aec79cafc2e8" - integrity sha512-t97w3zi5Kn/LEWGA6D9qxoO0LBOG+lK2FjlEdCwDQatffB/+vYrzZ/CLYVQSoyFZAlsDoBasVoYSWZK1n39aHA== - dependencies: - oboe "2.1.4" - underscore "1.9.1" - web3-core-helpers "1.2.2" - -web3-providers-ipc@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.8.1.tgz#6128a3a3a824d06bf0efcfe86325401f8691a5ca" - integrity sha512-nw/W5nclvi+P2z2dYkLWReKLnocStflWqFl+qjtv0xn3MrUTyXMzSF0+61i77+16xFsTgzo4wS/NWIOVkR0EFA== - dependencies: - oboe "2.1.5" - web3-core-helpers "1.8.1" - web3-providers-ipc@1.8.2: version "1.8.2" resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.8.2.tgz#e52a7250f40c83b99a2482ec5b4cf2728377ae5c" @@ -24982,24 +15761,6 @@ web3-providers-ws@1.10.0: web3-core-helpers "1.10.0" websocket "^1.0.32" -web3-providers-ws@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.2.2.tgz#d2c05c68598cea5ad3fa6ef076c3bcb3ca300d29" - integrity sha512-Wb1mrWTGMTXOpJkL0yGvL/WYLt8fUIXx8k/l52QB2IiKzvyd42dTWn4+j8IKXGSYYzOm7NMqv6nhA5VDk12VfA== - dependencies: - underscore "1.9.1" - web3-core-helpers "1.2.2" - websocket "github:web3-js/WebSocket-Node#polyfill/globalThis" - -web3-providers-ws@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.8.1.tgz#5e5370e07eb8c615ed298ebc8602b283c7b7d649" - integrity sha512-TNefIDAMpdx57+YdWpYZ/xdofS0P+FfKaDYXhn24ie/tH9G+AB+UBSOKnjN0KSadcRSCMBwGPRiEmNHPavZdsA== - dependencies: - eventemitter3 "4.0.4" - web3-core-helpers "1.8.1" - websocket "^1.0.32" - web3-providers-ws@1.8.2: version "1.8.2" resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.8.2.tgz#56a2b701387011aca9154ca4bc06ea4b5f27e4ef" @@ -25009,23 +15770,6 @@ web3-providers-ws@1.8.2: web3-core-helpers "1.8.2" websocket "^1.0.32" -web3-providers@1.0.0-beta.55: - version "1.0.0-beta.55" - resolved "https://registry.yarnpkg.com/web3-providers/-/web3-providers-1.0.0-beta.55.tgz#639503517741b69baaa82f1f940630df6a25992b" - integrity sha512-MNifc7W+iF6rykpbDR1MuX152jshWdZXHAU9Dk0Ja2/23elhIs4nCWs7wOX9FHrKgdrQbscPoq0uy+0aGzyWVQ== - dependencies: - "@babel/runtime" "^7.3.1" - "@types/node" "^10.12.18" - eventemitter3 "3.1.0" - lodash "^4.17.11" - url-parse "1.4.4" - web3-core "1.0.0-beta.55" - web3-core-helpers "1.0.0-beta.55" - web3-core-method "1.0.0-beta.55" - web3-utils "1.0.0-beta.55" - websocket "^1.0.28" - xhr2-cookies "1.1.0" - web3-shh@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.10.0.tgz#c2979b87e0f67a7fef2ce9ee853bd7bfbe9b79a8" @@ -25036,26 +15780,6 @@ web3-shh@1.10.0: web3-core-subscriptions "1.10.0" web3-net "1.10.0" -web3-shh@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.2.2.tgz#44ed998f2a6ba0ec5cb9d455184a0f647826a49c" - integrity sha512-og258NPhlBn8yYrDWjoWBBb6zo1OlBgoWGT+LL5/LPqRbjPe09hlOYHgscAAr9zZGtohTOty7RrxYw6Z6oDWCg== - dependencies: - web3-core "1.2.2" - web3-core-method "1.2.2" - web3-core-subscriptions "1.2.2" - web3-net "1.2.2" - -web3-shh@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.8.1.tgz#028a95cf9d3a36020380938b9a127610efbb9be7" - integrity sha512-sqHgarnfcY2Qt3PYS4R6YveHrDy7hmL09yeLLHHCI+RKirmjLVqV0rc5LJWUtlbYI+kDoa5gbgde489M9ZAC0g== - dependencies: - web3-core "1.8.1" - web3-core-method "1.8.1" - web3-core-subscriptions "1.8.1" - web3-net "1.8.1" - web3-shh@1.8.2: version "1.8.2" resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.8.2.tgz#217a417f0d6e243dd4d441848ffc2bd164cea8a0" @@ -25066,22 +15790,6 @@ web3-shh@1.8.2: web3-core-subscriptions "1.8.2" web3-net "1.8.2" -web3-utils@1.0.0-beta.55: - version "1.0.0-beta.55" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.0.0-beta.55.tgz#beb40926b7c04208b752d36a9bc959d27a04b308" - integrity sha512-ASWqUi8gtWK02Tp8ZtcoAbHenMpQXNvHrakgzvqTNNZn26wgpv+Q4mdPi0KOR6ZgHFL8R/9b5BBoUTglS1WPpg== - dependencies: - "@babel/runtime" "^7.3.1" - "@types/bn.js" "^4.11.4" - "@types/node" "^10.12.18" - bn.js "4.11.8" - eth-lib "0.2.8" - ethjs-unit "^0.1.6" - lodash "^4.17.11" - number-to-bn "1.7.0" - randombytes "^2.1.0" - utf8 "2.1.1" - web3-utils@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.10.0.tgz#ca4c1b431a765c14ac7f773e92e0fd9377ccf578" @@ -25095,47 +15803,7 @@ web3-utils@1.10.0: randombytes "^2.1.0" utf8 "3.0.0" -web3-utils@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.1.tgz#21466e38291551de0ab34558de21512ac4274534" - integrity sha512-Mrcn3l58L+yCKz3zBryM6JZpNruWuT0OCbag8w+reeNROSGVlXzUQkU+gtAwc9JCZ7tKUyg67+2YUGqUjVcyBA== - dependencies: - bn.js "4.11.8" - eth-lib "0.2.7" - ethjs-unit "0.1.6" - number-to-bn "1.7.0" - randomhex "0.1.5" - underscore "1.9.1" - utf8 "3.0.0" - -web3-utils@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.2.tgz#b53a08c40d2c3f31d3c4a28e7d749405df99c8c0" - integrity sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A== - dependencies: - bn.js "4.11.8" - eth-lib "0.2.7" - ethereum-bloom-filters "^1.0.6" - ethjs-unit "0.1.6" - number-to-bn "1.7.0" - randombytes "^2.1.0" - underscore "1.9.1" - utf8 "3.0.0" - -web3-utils@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.8.1.tgz#f2f7ca7eb65e6feb9f3d61056d0de6bbd57125ff" - integrity sha512-LgnM9p6V7rHHUGfpMZod+NST8cRfGzJ1BTXAyNo7A9cJX9LczBfSRxJp+U/GInYe9mby40t3v22AJdlELibnsQ== - dependencies: - bn.js "^5.2.1" - ethereum-bloom-filters "^1.0.6" - ethereumjs-util "^7.1.0" - ethjs-unit "0.1.6" - number-to-bn "1.7.0" - randombytes "^2.1.0" - utf8 "3.0.0" - -web3-utils@1.8.2, web3-utils@^1.0.0-beta.31: +web3-utils@1.8.2: version "1.8.2" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.8.2.tgz#c32dec5e9b955acbab220eefd7715bc540b75cc9" integrity sha512-v7j6xhfLQfY7xQDrUP0BKbaNrmZ2/+egbqP9q3KYmOiPpnvAfol+32slgL0WX/5n8VPvKCK5EZ1HGrAVICSToA== @@ -25148,7 +15816,7 @@ web3-utils@1.8.2, web3-utils@^1.0.0-beta.31: randombytes "^2.1.0" utf8 "3.0.0" -web3-utils@^1.10.0: +web3-utils@^1.0.0-beta.31, web3-utils@^1.10.0: version "1.10.3" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.10.3.tgz#f1db99c82549c7d9f8348f04ffe4e0188b449714" integrity sha512-OqcUrEE16fDBbGoQtZXWdavsPzbGIDc5v3VrRTZ0XrIpefC/viZ1ZU9bGEemazyS0catk/3rkOOxpzTfY+XsyQ== @@ -25162,7 +15830,7 @@ web3-utils@^1.10.0: randombytes "^2.1.0" utf8 "3.0.0" -web3@*, web3@1.8.2, web3@^1.2.4: +web3@*: version "1.8.2" resolved "https://registry.yarnpkg.com/web3/-/web3-1.8.2.tgz#95a4e5398fd0f01325264bf8e5e8cdc69a7afe86" integrity sha512-92h0GdEHW9wqDICQQKyG4foZBYi0OQkyg4CRml2F7XBl/NG+fu9o6J19kzfFXzSBoA4DnJXbyRgj/RHZv5LRiw== @@ -25188,54 +15856,6 @@ web3@1.10.0: web3-shh "1.10.0" web3-utils "1.10.0" -web3@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/web3/-/web3-1.2.2.tgz#b1b8b69aafdf94cbaeadbb68a8aa1df2ef266aec" - integrity sha512-/ChbmB6qZpfGx6eNpczt5YSUBHEA5V2+iUCbn85EVb3Zv6FVxrOo5Tv7Lw0gE2tW7EEjASbCyp3mZeiZaCCngg== - dependencies: - "@types/node" "^12.6.1" - web3-bzz "1.2.2" - web3-core "1.2.2" - web3-eth "1.2.2" - web3-eth-personal "1.2.2" - web3-net "1.2.2" - web3-shh "1.2.2" - web3-utils "1.2.2" - -web3@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/web3/-/web3-1.8.1.tgz#8ea67215ef5f3a6f6d3381800b527242ea22885a" - integrity sha512-tAqFsQhGv340C9OgRJIuoScN7f7wa1tUvsnnDUMt9YE6J4gcm7TV2Uwv+KERnzvV+xgdeuULYpsioRRNKrUvoQ== - dependencies: - web3-bzz "1.8.1" - web3-core "1.8.1" - web3-eth "1.8.1" - web3-eth-personal "1.8.1" - web3-net "1.8.1" - web3-shh "1.8.1" - web3-utils "1.8.1" - -web3@^0.16.0: - version "0.16.0" - resolved "https://registry.yarnpkg.com/web3/-/web3-0.16.0.tgz#a4554175cd462943035b1f1d39432f741c6b6019" - integrity sha512-8vET/GI2qDtShXNtPkuWByWvPNou9ecuYI9OJswBdA+NUwe5WZKirHUWakS0y4mK6lGmOhv7mLN7cHCBhmQRyA== - dependencies: - bignumber.js "git+https://github.com/debris/bignumber.js#master" - crypto-js "^3.1.4" - utf8 "^2.1.1" - xmlhttprequest "*" - -web3@^0.18.2: - version "0.18.4" - resolved "https://registry.yarnpkg.com/web3/-/web3-0.18.4.tgz#81ec1784145491f2eaa8955b31c06049e07c5e7d" - integrity sha512-TG+CtszzJHRHq+1T0AJVN4ATDvNn4QIAIEnErTgx2jj9oCa5ggOqZv3Ub0RAF+Yr2F/e5F6UFpEUSH9QK7w50Q== - dependencies: - bignumber.js "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" - crypto-js "^3.1.4" - utf8 "^2.1.1" - xhr2 "*" - xmlhttprequest "*" - webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -25246,7 +15866,7 @@ webidl-conversions@^4.0.2: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== -websocket@^1.0.28, websocket@^1.0.32: +websocket@^1.0.32: version "1.0.34" resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111" integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== @@ -25258,26 +15878,6 @@ websocket@^1.0.28, websocket@^1.0.32: utf-8-validate "^5.0.2" yaeti "^0.0.6" -"websocket@github:web3-js/WebSocket-Node#polyfill/globalThis": - version "1.0.29" - resolved "https://codeload.github.com/web3-js/WebSocket-Node/tar.gz/ef5ea2f41daf4a2113b80c9223df884b4d56c400" - dependencies: - debug "^2.2.0" - es5-ext "^0.10.50" - nan "^2.14.0" - typedarray-to-buffer "^3.1.5" - yaeti "^0.0.6" - -whatwg-fetch@>=0.10.0, whatwg-fetch@^3.4.1: - version "3.6.2" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" - integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA== - -whatwg-mimetype@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz#5fa1a7623867ff1af6ca3dc72ad6b8a4208beba7" - integrity sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q== - whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" @@ -25335,7 +15935,7 @@ which-typed-array@^1.1.11, which-typed-array@^1.1.13: gopd "^1.0.1" has-tostringtag "^1.0.0" -which-typed-array@^1.1.2, which-typed-array@^1.1.9: +which-typed-array@^1.1.2: version "1.1.9" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== @@ -25347,28 +15947,21 @@ which-typed-array@^1.1.2, which-typed-array@^1.1.9: has-tostringtag "^1.0.0" is-typed-array "^1.1.10" -which@1.3.1, which@^1.1.1, which@^1.2.12, which@^1.2.14, which@^1.2.9: +which@^1.2.9: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== dependencies: isexe "^2.0.0" -which@2.0.2, which@^2.0.1, which@^2.0.2: +which@^2.0.1, which@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.0.0" -wide-align@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== - dependencies: - string-width "^1.0.2 || 2" - -wide-align@^1.1.0, wide-align@^1.1.5: +wide-align@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== @@ -25396,11 +15989,6 @@ wif@^2.0.6: dependencies: bs58check "<3.0.0" -window-size@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.4.tgz#f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876" - integrity sha512-2thx4pB0cV3h+Bw7QmMXcEbdmOzv9t0HFplJH/Lz6yu60hXYy5RT8rUu+wlIreVxWsGN20mo+MHeCSfUpQBwPw== - window-size@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" @@ -25418,35 +16006,11 @@ winston@2.x: isstream "0.1.x" stack-trace "0.0.x" -word-wrap@~1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== - wordwrap@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== -workerpool@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.0.0.tgz#85aad67fa1a2c8ef9386a1b43539900f61d03d58" - integrity sha512-fU2OcNA/GVAJLLyKUoHkAgIhKb0JoCpSjLC/G2vYKxUjVmQwGbRVeoPJ1a8U4pnVofz4AQV5Y/NEw8oKqxEBtA== - -workerpool@6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" - integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== - -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" @@ -25481,21 +16045,21 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" - integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== dependencies: - ansi-styles "^6.1.0" - string-width "^5.0.1" - strip-ansi "^7.0.1" + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -write-file-atomic@^2.0.0, write-file-atomic@^2.4.2: +write-file-atomic@^2.4.2: version "2.4.3" resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ== @@ -25555,20 +16119,6 @@ write-pkg@^4.0.0: type-fest "^0.4.1" write-json-file "^3.2.0" -write-stream@~0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/write-stream/-/write-stream-0.4.3.tgz#83cc8c0347d0af6057a93862b4e3ae01de5c81c1" - integrity sha512-IJrvkhbAnj89W/GAVdVgbnPiVw5Ntg/B4tc/MUCIEwj/g6JIww1DWJyB/yBMT3yw2/TkT6IUZ0+IYef3flEw8A== - dependencies: - readable-stream "~0.0.2" - -write@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" - integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== - dependencies: - mkdirp "^0.5.1" - ws@7.4.6: version "7.4.6" resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" @@ -25579,11 +16129,6 @@ ws@8.12.0: resolved "https://registry.yarnpkg.com/ws/-/ws-8.12.0.tgz#485074cc392689da78e1828a9ff23585e06cddd8" integrity sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig== -ws@8.13.0: - version "8.13.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" - integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== - ws@8.2.3: version "8.2.3" resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba" @@ -25598,23 +16143,6 @@ ws@^3.0.0: safe-buffer "~5.1.0" ultron "~1.1.0" -ws@^5.1.1: - version "5.2.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.3.tgz#05541053414921bc29c63bee14b8b0dd50b07b3d" - integrity sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA== - dependencies: - async-limiter "~1.0.0" - -ws@^7.2.0: - version "7.5.9" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" - integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== - -xdg-basedir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" - integrity sha512-1Dly4xqlulvPD3fZUQJLY+FUIeqN3N2MM3uqe4rCJftAvOjFa3jFGfctOgluGx4ahPbUCsZkmJILiP0Vi4T6lQ== - xhr-request-promise@^0.1.2: version "0.1.3" resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz#2d5f4b16d8c6c893be97f1a62b0ed4cf3ca5f96c" @@ -25642,12 +16170,7 @@ xhr2-cookies@1.1.0: dependencies: cookiejar "^2.1.1" -xhr2@*: - version "0.2.1" - resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.2.1.tgz#4e73adc4f9cfec9cbd2157f73efdce3a5f108a93" - integrity sha512-sID0rrVCqkVNUn8t6xuv9+6FViXjUVXq8H5rWOH2rz9fDNQEd4g0EA2XlcEdJXRz5BMEn4O1pJFdT+z4YHhoWw== - -xhr@^2.0.4, xhr@^2.2.0, xhr@^2.3.3: +xhr@^2.0.4, xhr@^2.3.3: version "2.6.0" resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.6.0.tgz#b69d4395e792b4173d6b7df077f0fc5e4e2b249d" integrity sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA== @@ -25670,7 +16193,7 @@ xmlbuilder@~11.0.0: resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== -xmlhttprequest@*, xmlhttprequest@1.8.0: +xmlhttprequest@1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" integrity sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA== @@ -25680,27 +16203,12 @@ xorshift@^1.1.1: resolved "https://registry.yarnpkg.com/xorshift/-/xorshift-1.2.0.tgz#30a4cdd8e9f8d09d959ed2a88c42a09c660e8148" integrity sha512-iYgNnGyeeJ4t6U11NpA/QiKy+PXn5Aa3Azg5qkwIFz1tBLllQrjjsk9yzD7IAK0naNU4JxdeDgqW9ov4u/hc4g== -xss@^1.0.8: - version "1.0.14" - resolved "https://registry.yarnpkg.com/xss/-/xss-1.0.14.tgz#4f3efbde75ad0d82e9921cc3c95e6590dd336694" - integrity sha512-og7TEJhXvn1a7kzZGQ7ETjdQVS2UfZyTlsEdDOqvQF7GoxNfY+0YLCzBy1kPdsDDx4QuNAonQPddpsn6Xl/7sw== - dependencies: - commander "^2.20.3" - cssfilter "0.0.10" - -xtend@^4.0.0, xtend@^4.0.1, xtend@^4.0.2, xtend@~4.0.0, xtend@~4.0.1: +xtend@^4.0.0, xtend@~4.0.0, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== -xtend@~2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" - integrity sha512-vMNKzr2rHP9Dp/e1NQFnLQlwlhp9L/LfvnsVdHxN1f+uggyVI3i08uD14GPvCToPkdsRfyPqIyYGmIk58V98ZQ== - dependencies: - object-keys "~0.4.0" - -y18n@^3.2.0, y18n@^3.2.1: +y18n@^3.2.1: version "3.2.2" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696" integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ== @@ -25735,19 +16243,11 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@^1.10.0, yaml@^1.10.2: +yaml@^1.10.0: version "1.10.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== -yargs-parser@13.1.2, yargs-parser@^13.1.2: - version "13.1.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" - integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - yargs-parser@20.2.4: version "20.2.4" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" @@ -25758,10 +16258,10 @@ yargs-parser@21.1.1, yargs-parser@^21.0.1, yargs-parser@^21.1.1: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== -yargs-parser@^15.0.1: - version "15.0.3" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-15.0.3.tgz#316e263d5febe8b38eef61ac092b33dfcc9b1115" - integrity sha512-/MVEVjTXy/cGAjdtQf8dW3V9b97bPN7rNn8ETj6BmAQL7ibC7O1Q9SPJbGjgh3SlwoBNXMzj/ZGIj8mBgl12YA== +yargs-parser@^13.1.2: + version "13.1.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" + integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" @@ -25794,67 +16294,6 @@ yargs-parser@^9.0.2: dependencies: camelcase "^4.1.0" -yargs-unparser@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" - integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== - dependencies: - flat "^4.1.0" - lodash "^4.17.15" - yargs "^13.3.0" - -yargs-unparser@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" - integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== - dependencies: - camelcase "^6.0.0" - decamelize "^4.0.0" - flat "^5.0.2" - is-plain-obj "^2.1.0" - -yargs@13.3.2, yargs@^13.2.4, yargs@^13.3.0: - version "13.3.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" - integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== - dependencies: - cliui "^5.0.0" - find-up "^3.0.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^3.0.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^13.1.2" - -yargs@16.2.0, yargs@^16.2.0: - version "16.2.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" - 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" - -yargs@17.7.2, yargs@^17.7.1, yargs@^17.7.2: - version "17.7.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" - integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== - dependencies: - cliui "^8.0.1" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" - y18n "^5.0.5" - yargs-parser "^21.1.1" - yargs@^11.0.0: version "11.1.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.1.tgz#5052efe3446a4df5ed669c995886cc0f13702766" @@ -25873,13 +16312,12 @@ yargs@^11.0.0: y18n "^3.2.1" yargs-parser "^9.0.2" -yargs@^14.0.0: - version "14.2.3" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-14.2.3.tgz#1a1c3edced1afb2a2fea33604bc6d1d8d688a414" - integrity sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg== +yargs@^13.2.4: + version "13.3.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" + integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== dependencies: cliui "^5.0.0" - decamelize "^1.2.0" find-up "^3.0.0" get-caller-file "^2.0.1" require-directory "^2.1.1" @@ -25888,7 +16326,7 @@ yargs@^14.0.0: string-width "^3.0.0" which-module "^2.0.0" y18n "^4.0.0" - yargs-parser "^15.0.1" + yargs-parser "^13.1.2" yargs@^15.1.0: version "15.4.1" @@ -25907,7 +16345,20 @@ yargs@^15.1.0: y18n "^4.0.0" yargs-parser "^18.1.2" -yargs@^17.3.1, yargs@^17.5.1, yargs@^17.6.2: +yargs@^16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + 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" + +yargs@^17.3.1, yargs@^17.6.2: version "17.7.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.1.tgz#34a77645201d1a8fc5213ace787c220eabbd0967" integrity sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw== @@ -25920,18 +16371,18 @@ yargs@^17.3.1, yargs@^17.5.1, yargs@^17.6.2: y18n "^5.0.5" yargs-parser "^21.1.1" -yargs@^3.10.0: - version "3.32.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.32.0.tgz#03088e9ebf9e756b69751611d2a5ef591482c995" - integrity sha512-ONJZiimStfZzhKamYvR/xvmgW3uEkAUFSP91y2caTEPhzF6uP2JfPiVZcq66b/YR0C3uitxSV7+T1x8p5bkmMg== +yargs@^17.7.1, yargs@^17.7.2: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== dependencies: - camelcase "^2.0.1" - cliui "^3.0.3" - decamelize "^1.1.1" - os-locale "^1.4.0" - string-width "^1.0.1" - window-size "^0.1.4" - y18n "^3.2.0" + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" yargs@^4.7.1: version "4.8.1" @@ -25958,14 +16409,6 @@ yarn@^1.21.1: resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.19.tgz#4ba7fc5c6e704fce2066ecbfb0b0d8976fe62447" integrity sha512-/0V5q0WbslqnwP91tirOvldvYISzaqhClxzyUKXYxs07yUILIs5jx/k6CFe8bvKSkds5w+eiOqta39Wk3WxdcQ== -yauzl@^2.4.2: - version "2.10.0" - resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" - integrity sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g== - dependencies: - buffer-crc32 "~0.2.3" - fd-slicer "~1.1.0" - yn@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" @@ -25975,13 +16418,3 @@ yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== - -yocto-queue@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251" - integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g== - -zod@^3.21.4: - version "3.22.4" - resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.4.tgz#f31c3a9386f61b1f228af56faa9255e845cf3fff" - integrity sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==